Take a look at these two functions:
void function1() {
int x;
int y;
int z;
int *ret;
}
void function2() {
char buffer1[4];
char buffer2[4];
char buffer3[4];
int *ret;
}
If I break at function1()
in gdb
, and print the addresses of the variables, I get this:
(gdb) p &x
$1 = (int *) 0xbffff380
(gdb) p &y
$2 = (int *) 0xbffff384
(gdb) p &z
$3 = (int *) 0xbffff388
(gdb) p &ret
$4 = (int **) 0xbffff38c
If I do the same thing at function2()
, I get this:
(gdb) p &buffer1
$1 = (char (*)[4]) 0xbffff388
(gdb) p &buffer2
$2 = (char (*)[4]) 0xbffff384
(gdb) p &buffer3
$3 = (char (*)[4]) 0xbffff380
(gdb) p &ret
$4 = (int **) 0xbffff38c
You'll notice that in both functions, ret
is stored closest to the top of the stack. In function1()
, it is followed by z
, y
, and finally x
. In function2()
, ret
is followed by buffer1
, then buffer2
and buffer3
. Why is the storage order changed? We're using the same amount of memory in both cases (4 byte int
s vs 4 byte char
arrays), so it can't be an issue of padding. What reasons could there be for this reordering, and furthermore, is it possible by looking at the C code to determine ahead of time how the local variables will be ordered?
Now I'm aware that the ANSI spec for C says nothing about the order that local variables are stored in and that the compiler is allowed to chose its own order, but I would imagine that the compiler has rules as to how it takes care of this, and explanations as to why those rules were made to be as they are.
For reference I'm using GCC 4.0.1 on Mac OS 10.5.7