Когда выделяется память во время компиляции? - PullRequest
2 голосов
/ 06 июня 2009

Когда я пишу

int main()
{
    int j;
}

Память для 'j' выделяется во время компиляции, но когда во время компиляции? Каковы различные этапы компиляции, когда память выделяется для переменной? Что если j был глобальным?

Ответы [ 8 ]

8 голосов
/ 06 июня 2009

Полагаю, вы все перепутали.

Компилятор не выделяет память для переменных - он генерирует код, который выделяет память для переменных во время выполнения. Для глобалов будет добавлен код запуска программы.

5 голосов
/ 06 июня 2009

В 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

Здесь следует обратить внимание на две вещи:

  1. Адрес i постоянен каждый раз, когда на него ссылаются
  2. Адрес n (переменная, локальная для функции foo, меняется с каждым вызовом foo. Фактически, он будет уменьшаться каждый раз, так как стек растет вниз.
5 голосов
/ 06 июня 2009

Не во время компиляции ваше int j будет выделено при запуске приложения, когда приложение войдет в область действия main () (фактически это не будет выделено технически, так как стек используется), глобальные переменные получат выделяется во время выполнения перед входом в область видимости main ().

2 голосов
/ 06 июня 2009

Компиляция генерирует исполняемый код для программы. Память программы выделяется при запуске этого исполняемого кода.

2 голосов
/ 06 июня 2009

Процесс компиляции не выделяет память. Он генерирует код, который выделяет память:)

В этом случае j будет так называемой переменной стека, и она будет выделена при входе в функцию main (). Вместо этого в куче размещаются глобальные и статические переменные.

Вот краткое объяснение: http://www.costech.or.tz/cs231/websites/C%20Programming/www-ee.eng.hawaii.edu/Courses/ee150/Book/chap14/subsection2.1.1.8.html. Я посмотрю, смогу ли я найти лучшее.

0 голосов
/ 06 июня 2009

Я думаю, что вы смотрите на этапах компиляции, а не на выделение памяти для 'j'. Поскольку я так думаю, вот что происходит:

Как только вы передадите свой исходный код компилятору C, первым этапом будет лексический и семантический анализ, в котором синтаксис и семантика исходного кода анализируются на предмет корректности. Если были обнаружены ошибки, компилятор сообщает об этом и не предпринимает никаких действий. Если ошибок не обнаружено, он переходит к генерации промежуточного представления исходного кода, обычно после различных оптимизаций. Это промежуточное представление может быть на родном языке (нативном для ОС / архитектуры, как в C) или независимом от платформы байт-коде (например, Python / Java ..). На этом функция компилятора заканчивается.

Выделение памяти происходит только при выполнении кода. Это время выполнения программы. Это происходит только после этапа компиляции, который, вероятно, вы не хотели бы знать здесь. Если вы хотите, пожалуйста, дайте мне знать. Я постараюсь добавить все, что знаю.

НТН.

0 голосов
/ 06 июня 2009

Память выделяется не во время компиляции, а во время выполнения. Компилятор только что сгенерировал машинный код, который будет выполнять вашу программу, фактические выделения происходят во время выполнения. В этом случае переменная не используется и для нее не будет выпущен код.

0 голосов
/ 06 июня 2009

Это зависит от компилятора, где разместить j. Обычно локальные переменные помещаются в стек, и, как таковой, для вашего конкретного примера, компилятор, вероятно, зарезервирует место в стеке на время основной функции. Обратите внимание, что это отличается от глобальной переменной памяти, которая может получать свою собственную память.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...