Search code examples
cpointerslong-integertypecasting-operator

What happens when address of a long variable is store in char pointer?


I'm trying to understand what happens when I store a pointer of different data type into char pointer. I understand everything except why these two lines:

…
char *cc;
long l;
…
cc = &l;
printf("\nc: %ld, cc: %u", *cc, cc);

are printing this:

c: 4294967211, cc: 591272048

instead of this->

c: 171 (0xAB), cc: 591272048?

Code:

#include <stdio.h>    
int main()
{
  char c = 65, *cc;
  int i = 0x12345678;
  long l = 0x12345AB;
  float f = 3.14;

  cc = &c;
  printf("c: %c, cc: %u", *cc, cc);
  cc = &i;
  printf("\nc: %d, cc: %u", *cc, cc);
  cc = &l;
  printf("\nc: %ld, cc: %u", *cc, cc);
  cc = &f;
  printf("\nc: %f, cc: %u", *cc, cc);
}

Prints:

c: A, cc: 591272063
c: 120, cc: 591272056
c: 4294967211, cc: 591272048
c: 0.000000, cc: 4294967235

Solution

  • You are invoking Undefined Behaviour, and get... undefined results! This can happen if on your target architecture:

    • the char type is signed
    • the int type is 32 bits long
    • the long type is 64 bits long
    • endianness is little endian
    • negative numbers use 2's complement representation

    Then when executing

    cc = &l;
    printf("\nc: %ld, cc: %u", *cc, cc);
    

    *cc is the last byte of l and is 0xAB (or -85) it is promoted to the signed integer 0xFFFFFFAB. You already have a lot of unspecified behaviour until that point...

    But when you use %ld in printf, the program tries to read a little endian long when you only passed a char value which was promoted to int. The 32 highest order bits happen to be 0 here but that part is UB and anything could happen. But as a long, 0xFFFFFFAB is indeed 4 294 967 211

    But as you invoked UB, you cannot rely on that...

    TL/DR: your code invokes Undefined Behaviour and result could be anything.