Взгляните на эти две функции:
void function1() {
int x;
int y;
int z;
int *ret;
}
void function2() {
char buffer1[4];
char buffer2[4];
char buffer3[4];
int *ret;
}
Если я сломался на function1()
в gdb
и напечатаю адреса переменных, я получаю следующее:
(gdb) p &x
$1 = (int *) 0xbffff380
(gdb) p &y
$2 = (int *) 0xbffff384
(gdb) p &z
$3 = (int *) 0xbffff388
(gdb) p &ret
$4 = (int **) 0xbffff38c
Если я делаю то же самое в function2()
, я получаю следующее:
(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
Вы заметите, что в обеих функциях ret
хранится ближе всего к вершине стека. В function1()
за ним следуют z
, y
и, наконец, x
. В function2()
за ret
следует buffer1
, затем buffer2
и buffer3
. Почему порядок хранения изменился? Мы используем тот же объем памяти в обоих случаях (4 байта int
против 4 байт char
массивов), поэтому это не может быть проблемой заполнения. Какие причины могут быть для этого переупорядочения, и, кроме того, возможно ли это, посмотрев на код С, заранее определить, как будут упорядочены локальные переменные?
Теперь я знаю, что спецификация ANSI для C ничего не говорит о порядке хранения локальных переменных и что компилятору разрешено выбирать свой собственный порядок, но я бы предположил, что у компилятора есть правила относительно того, как это сделать заботится об этом и объясняет, почему эти правила были такими, какие они есть.
Для справки Я использую GCC 4.0.1 в Mac OS 10.5.7