Search code examples
cstructhexoffsetmemory-address

C how could an unsigned int only takes two bytes?


I'm playing around with pointers and I've noticed one weird thing.

I have a struct as follow:

typedef struct list_element_struct {
    uint32_t x; 
    uint32_t y; 
    uint32_t z; 
    struct list_element_struct *next; 
    }list_element;

As far as I know, the size of unsigned int is 4 bytes, and the size of a pointer is 8 bytes. Also there are 8 bytes aligned happened here so the size of this struct is 24 bytes.

I've initialized a list of above struct objects with list_element els[5]; and also set every piece of data in there to 0 with memset(els,0,5*sizeof(list_element));

Right now I'm trying to see their memory locations with these piece of code:

printf("%p start location of els\n", &(els));
printf("%p start location of els->x\n", &(els->x));
printf("%p start location of els->y\n", &(els->y));
printf("%p start location of els->z\n", &(els->z));
printf("%p start location of els->next(pointer)\n", &(els->next));
printf("%p start location of els+1\n", &(els[1]));

What I have as printed out is:

0x7ffeeba4a970 start location of els
0x7ffeeba4a970 start location of els->x
0x7ffeeba4a974 start location of els->y
0x7ffeeba4a978 start location of els->z
0x7ffeeba4a980 start location of els->next(pointer)
0x7ffeeba4a988 start location of els+1

Here is the weird thing. Why does els->z only takes two bytes? it really should take 4 like x and y.


Solution

  • Those numbers are hexadecimal. The difference between 0x7ffeeba4a978 and 0x7ffeeba4a980 is not 2 but 8.

    To forestall your next question, the reason it's 8 and not 4 is likely due to alignment requirement. Many 64-bit systems either require or prefer to align their 8-byte pointers to 8-byte boundaries, i.e. to addresses which are a multiple of 8 (so that their least-significant hex digit is either 8 or 0). So the compiler leaves 4 bytes of padding between z and next to achieve this.