2009-06-06 4 views
2

Когда я пишуКогда память выделяется во время компиляции?

int main() 
{ 
    int j; 
} 

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

+1

Пожалуйста, внесите свой вопрос. Двойные пробелы разрывают линию. –

+1

как-то у меня такое ощущение, что ваш вопрос неоднозначен, а ваше имя и описание вопроса непоследовательны. – 2009-06-06 16:16:44

+0

Если речь идет о распределении памяти для разных областей на C, тогда заголовок должен быть отредактирован в соответствии с этим. – Doug

ответ

5

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

+0

Этот ответ неверный: хранилище для 'j' будет * не * выделяться при запуске приложения (обычно между 1000 процессами между запуском процесса и вводом «main» обычно назначается 1000 команд). И глобальные * * выделяются при запуске процесса, * long * до main. –

+0

Я бы рассмотрел возможность ввода main() части запуска приложения. Удалено «просто». –

0

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

8

Я думаю, вы смешиваете вещи.

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

2

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

В этом случае 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

отсутствует «нет» или так в первом предложении? –

+0

Да, это было, извините :) – Thorarin

+0

Теперь ваш ответ почти правильный: глобальные и статические переменные * не * выделены на кучу; они загружаются в память загрузчиком программ при запуске процесса. Мне кажется, что такой простой вопрос породил так много неправильных ответов. Возможно, я должен использовать это как вопрос для интервью. –

2

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

+0

Было бы лучше сказать «память данных», а не «программную память»? –

0

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

0

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

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

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

HTH.

5

В C основной скомпилирован так же, как и любая другая функция: любые переменные, объявленные в главном, будут «выделены» в стеке. Фрейм стека - это часть стека, которая используется одним вызовом функции. Рамка содержит слоты для всех локалей, используемых внутри функции. Эта память считается временной, поскольку, когда функция возвращается, этот кадр будет выскользнут из стека.

Компилятор 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. Фактически, он будет уменьшаться каждый раз, так как стек растет вниз.
Смежные вопросы