Hello I have this example:
int main(){
int x = 300;
char* p = (char*)&x;
printf("%s\n", p);
printf("%d\n", *p);
}
The output:
,
44
Is it Undefined Behavior casting the address of
x
tochar*
as long asx
has a positive value that overflows asigned char
?Why I got this output?
,
and44
? I've tried to understand so I thought300 % 256 = 44
is converted and assigned top
so its character ASCII value is,
on my implementation.
What do you think and recommend?
CodePudding user response:
There is no UB here. Generally, going such things violates strict aliasing (causing UB), but there is an exception allowing you to use char
pointers to access any type.
300
is represented in memory as 4 bytes: 44 0 0 0
(assuming sizeof(int) == 4
, which is very common, and assuming little-endianness).
printf("%s\n", p);
interprets those 4 bytes as a C-string. You would get the same result by printing
const char str[4] = {44, 0, 0, 0}; // Same as `{',', '\0', '\0', '\0'}`
In theory, you could get UB if the byte representation of 300
didn't contain null bytes, as it would cause printf
to continue reading memory out of bounds of x
, looking for a null-terminator. But there are no real platforms where that's the case, so it should be safe.
And *p
accesses the first byte in the representation of x
, which is 44
.
If you were to try this code on a big-endian platform, you would get an empty string and a 0
respectively, since the byte representation of 300
would be 0 0 0 44
.
x
has a positive value that overflows asigned char
This isn't a problem.
CodePudding user response:
- Is it Undefined Behavior casting the address of
x
tochar*
as long as x has a positive value that overflows a signed char?
Regardless of the value of x
, this is not undefined behaviour; you are allowed to do a reinterpret_cast
from any pointer type to a char*
pointer, as long as there are no issues with const
.
Printing this value as a string is undefined behaviour, though: You may be on a system where int
just uses 16 bit, so none of the bytes of the int
accessible via the char
pointer may be 0 result in a byte that is 0; printf()
could therefore read past the memory guaranteed to be accessible.
- Why I got this output?
,
and44
? I've tried to understand so I thought300 % 256 = 44
is converted and assigned top
so its character ASCII value is,
on my implementation.
You're using a little-endian system using 32-bit int
s. This means 300 = 0x12C
is seen as array { 0x2C, 0x01, 0x00, 0x00 }
(little-endian systems store the least significant byte first).
Now, trying to print this as a string, you get the first char with the value 0x2C
, i.e. the ','
character, followed by a non-printable character 0x01
. The following 0x00
char terminates the string, so the output seen is just ,
.
When printing the pointer value as a decimal, the only thing printed is 0x2C
in decimal base, i.e. 44
.