0

So, I was trying some stuff and I noticed that if you read one address that contains 11111111 as an unsigned int it shows that is value is 4294967295 and not 255, why is that?

Example of the code:

    unsigned int a = 255;
    unsigned int* p = &a;
    char *p0 = (char*)p;
    cout << (void*)p0 << " " <<(unsigned int)*p0<<endl;
Lundin
  • 195,001
  • 40
  • 254
  • 396
ladca
  • 25
  • 5

2 Answers2

5
  • char *p0 = (char*)p; Here p0 points at the lowest byte of p. What value that happens to be stored there depends on endianess. Could be 0x00 (Big Endian) or 0xFF (Little Endian).
    What is CPU endianness?

  • *p0 here you access the contents of the supposed char. Since char has implementation-defined signedness, it could either manage numbers -128 to 127 (assuming 2's complement) or 0 to 255. Is char signed or unsigned by default?

  • Your particular system seems to use signed char, 2's complement, Little Endian. Meaning that the raw binary value 0xFF gets interpreted as -1 decimal.

  • (unsigned int)*p0 forces a conversion from -1 to unsigned int type. This is done after this well-defined rule (C 6.3.1.4, same rule applies in C++):

    Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.

  • -1 + UINT_MAX + one more =
    -1 + UINT_MAX + 1 =
    UINT_MAX =
    4294967295 on your 32 bit system.

Lesson learnt: never use char for anything but text, never use it to store values. If you need an 8 bit integer type or something to represent raw binary, use unsigned char or uint8_t.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • Thanks for the answer! Now this got me thinking: Is there any way of reading the bit content of an address (without considering it int, char, etc…)? – ladca Feb 16 '21 at 18:32
  • @ladca The bitwise operators only work with integer types. – Lundin Feb 17 '21 at 07:50
1

Line 4 is reading the representation of the object a as char, which is just about the only time it's legal (not undefined) to access an object with an lvalue not matching the actual type of the object. C allows plain char to be a signed or unsigned type (implementation-defined). On the implementation you're using, char is a signed type, and unsigned int is represented in little endian (low-order byte first), so you read the bit pattern with 8 one bits, and this represents the char value -1.

Subsequently converting (via cast or implicitly) the value -1 to unsigned int reduces it modulo UINT_MAX+1, producing the value UINT_MAX.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711