Home > Net >  Is casting an address of int whose value overflows a singed char to a pointer to char UB?
Is casting an address of int whose value overflows a singed char to a pointer to char UB?

Time:10-08

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 to char* as long as x has a positive value that overflows a signed char?

  • Why I got this output? , and 44? I've tried to understand so I thought 300 % 256 = 44 is converted and assigned to p 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 a signed char

This isn't a problem.

CodePudding user response:

  • Is it Undefined Behavior casting the address of x to char* 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? , and 44? I've tried to understand so I thought 300 % 256 = 44 is converted and assigned to p so its character ASCII value is , on my implementation.

You're using a little-endian system using 32-bit ints. 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.

  • Related