В C main скомпилируется так же, как и любая другая функция: любые переменные, объявленные в main, будут «размещены» в стеке. Кадр стека - это часть стека, которая используется одним вызовом функции. Кадр содержит слоты для всех местных жителей, используемых в функции. Эта память считается временной, поскольку при возврате функции этот кадр извлекается из стека.
Компилятор C назначит статический адрес глобальным переменным. Этот адрес считается частью "образа" двоичного файла и поэтому имеет статическое расположение в памяти. Компилятор C знает размер каждого типа, поэтому он может выделить необходимое количество места в макете памяти двоичного файла для каждой глобальной переменной. Тогда любой код, который обращается к этой переменной, просто ссылается на этот адрес.
Вы можете проверить адрес переменной с помощью следующего кода:
#include<stdio.h>
int i;
void foo(int n)
{
if(n > 2)
return;
printf("From foo &n = %xd\n", &n);
printf("From foo &i = %xd\n", &i);
foo(n+1);
}
int main()
{
printf("&i = %xd\n", &i);
foo(0);
return 0;
}
Запуск этого кода приводит к выводу, подобному:
./a.out
&i = 600934d
From foo &n = 38bc4efcd
From foo &i = 600934d
From foo &n = 38bc4eccd
From foo &i = 600934d
From foo &n = 38bc4e9cd
From foo &i = 600934d
Здесь следует обратить внимание на две вещи:
- Адрес i постоянен каждый раз, когда на него ссылаются
- Адрес n (переменная, локальная для функции
foo
, меняется с каждым вызовом foo. Фактически, он будет уменьшаться каждый раз, так как стек растет вниз.