26

I noticed something strange after compiling this code on my machine:

#include <stdio.h>

int main()
{
    printf("Hello, World!\n");

    int a,b,c,d;

    int e,f,g;

    long int h;

    printf("The addresses are:\n %0x \n %0x \n %0x \n %0x \n %0x \n %0x \n %0x \n %0x",
        &a,&b,&c,&d,&e,&f,&g,&h);

    return 0;
}

The result is the following. Notice that between every int address there is a 4-byte difference. However between the last int and the long int there is a 12-byte difference:

 Hello, World!
 The addresses are:

 da54dcac 
 da54dca8 
 da54dca4 
 da54dca0 
 da54dc9c 
 da54dc98 
 da54dc94 
 da54dc88
Boann
  • 109
yoyo_fun
  • 2,297

3 Answers3

81

It didn't take 12 bytes, it only took 8. However, the default alignment for an 8 byte long int on this platform is 8 bytes. As such, the compiler needed to move the long int to an address that's divisible by 8. The "obvious" address, da54dc8c, isn't divisible by 8 hence the 12 byte gap.

You should be able to test this. If you add another int prior to the long, so there are 8 of them, you should find that the long int will be aligned ok without a move. Now it'll be only 8 bytes from the previous address.

It's probably worth pointing out that, although this test should work, you shouldn't rely on the variables being organised this way. A C compiler is allowed to do all sorts of funky stuff to try to make your program run quickly including re-ordering variables (with some caveats).

Alex
  • 3,942
9

This is because your compiler is generating extra padding between variables to ensure they are correctly aligned in memory.

On most modern processors, if a value has an address that is a multiple of its size, it is more efficient to access it. If it had put h at the first available spot, its address would have been 0xda54dc8c, which isn't a multiple of 8, so would have been less efficient to use. The compiler knows about this and is adding a bit of unused space between your last two variables in order to make sure it happens.

Jules
  • 17,880
  • 2
  • 38
  • 65
2

Your test isn't necessarily testing what you think it is, because there is no requirement of the language to relate the address of any of these local variables to each other.

You would have to put these as fields in a struct in order to be able to infer something about storage allocation.

Local variables are not required to share storage next to each other in any particular manner. The compiler may insert a temporary variable anywhere within the stack, for example, which could be in between any two of these local variables.

By contrast, it wouldn't be allowed to insert a temporary variable into a struct, so if you printed the addresses of struct fields instead, you'd be comparing items intended allocated from the same logical chuck of memory (the struct).

Erik Eidt
  • 34,819