Порядок размещения локальной переменной в стеке
Взгляните на эти две функции:
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
массивов), так что это не может быть проблемой заполнения. Какие могут быть причины для такого переупорядочения, и, кроме того, возможно ли, взглянув на код C, заранее определить, как будут упорядочены локальные переменные?
Теперь я знаю, что спецификация ANSI для C ничего не говорит о порядке, в котором хранятся локальные переменные, и что компилятору разрешено выбирать свой собственный порядок, но я думаю, что у компилятора есть правила относительно того, как он заботится о это и объяснения того, почему эти правила были сделаны такими, какие они есть.
Для справки я использую GCC 4.0.1 в Mac OS 10.5.7