-1

I have the following variable var which is an unsigned 32bit value. I am working on a little endian system.

unsigned long var = 1;
// Representation: 00000000 00000000 00000000 00000001

Now I want to access the first and the last 16 bit via:

(((unsigned short*)&var)[0])) => 00000000 00000001

(((unsigned short*)&var)[1])) => 00000000 00000000

Is there any C documentation for this type of pointer adress type split? I got this working but I do not know how this works.

Thanks

Hunter McMillen
  • 59,865
  • 24
  • 119
  • 170
crizzo
  • 1
  • 1

1 Answers1

5

Generally, you can access any data type in C through a pointer to character type, such as unsigned char* or uint8_t*. If you cast var to such a character pointer, you get a pointer to the first byte:

unsigned char* cptr = (unsigned char*)&var;

You can then reference that pointer to get the contents, either by doing *cptr or cptr[0] - this means the same thing. On a little endian system you now have a pointer to the least significant byte. cptr[1] will give the byte after that, and so on.

However this is only guaranteed to work for character types! No other type like unsigned short can be used - that would give a so called "strict aliasing violation". What is the strict aliasing rule? Meaning that if you have code like this:

unsigned long var = 1;
*(unsigned short*)&var = 123;
if(var == 1)
  printf("Look mom, I violated strict aliasing!");

Then the compiler is free to generate code that executes the printf statement. Or it can also change var just like you expect and don't execute printf. Or it can crash and burn: it is undefined behavior, anything can happen. Bugs like this are frequent to appear on the gcc compiler in particular, with high optimization enabled.

Lundin
  • 195,001
  • 40
  • 254
  • 396