Что делает компилятор C с различными типами объявлений? - PullRequest
5 голосов
/ 05 июня 2011

Я понимаю это:

int i = 3;  // declaration with definition

Он говорит компилятору:

  1. Зарезервировать пространство в памяти для хранения целочисленного значения.
  2. Свяжите имя с памятьюlocation.
  3. Сохраните значение 3 в этом месте.

Но что говорит это объявление компилятору:

int i;  // declaration

Ответы [ 6 ]

4 голосов
/ 05 июня 2011

Объявление указывает компилятору зарезервировать место для переменной i и связать имя i с этим пробелом (ваши точки 1. и 2.).

Если i является глобальной переменной, она инициализируется 0.

Если это локальное значение, значение i не определено (возможно, мусор, т. Е. Какое-то случайное значение), и вам следует присвоить его перед прочтением.

3 голосов
/ 05 июня 2011

Существует два случая: в области видимости файла (т. Е. Для глобального объявления) и в функции.

В функции объявление int i; выполняет две функции: объявляет переменную с именем i, тип которой равен int, и резервирует некоторую память в памяти для помещения значения типа int. Что он не делает, так это дает переменной значение. Хранилище, используемое i, будет по-прежнему содержать мусор, который был там раньше. Вам нужно инициализировать переменную, то есть присвоить ей значение, прежде чем вы сможете прочитать значение из нее. Хорошие компиляторы предупредят вас, если вы не инициализируете переменную.

В области действия файла , int i также объявляет переменную с именем i. Остальное зависит от других вещей: это известно как предварительное определение . Вы можете иметь несколько таких объявлений в вашем файле. Не более одного из них может иметь инициализатор, что делает его полнофункциональным определением. Если ни одно из объявлений i в области видимости файла не имеет инициализатора, объявление также является определением, и существует неявная инициализация 0. Таким образом:

int i;
/* ... more code ...*/
int i;

является действительным, и i будет инициализирован в 0 (при условии, что это единственные объявления i в области видимости файла). Принимая во внимание:

int i;
int i = 3;

также допустимо, и i будет инициализировано 3 при запуске программы.

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

1 голос
/ 05 июня 2011

В нем говорится, чтобы зарезервировать место для целого числа, которое называется i.Что касается того, что находится там, зависит от компилятора и не определено.

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

Существует три вида памяти для объектов:

1) внешний (часто называемый «глобальным», но на самом деле это относится к области). Объекты здесь создаются до запуска программы; 2) стек (создается во время выполнения); 3) куча (например, неправильно).

"int i;" либо создает объект во внешней памяти, либо в стеке. Если он находится в функции, он создается в стеке (если «static» также не используется.

Объекты, созданные во внешней памяти, инициализируются нулями, если они не инициализированы явно (например, «int i = 3»;

Вы можете создать внешний объект в функции, используя ключевое слово «static».

int a; // external memory with "global" scope. Initialized to 0 implicitly.
static int b; // external memory with file (module) scope. Initialized to 0 implicitly.
int c = 3; // external memory initialized to 3.

f()
{
  int d; // created on the stack. Goes away when the block exits. Filled with random trash because there is no initialization.
  int e = 4; // stack object initialized to 3.
  static int f; // "f" is external but not global. Like all externals, it's implicitly initialized to zero.
  static int g = 3; // An external like f but initialized to 3.

}
0 голосов
/ 05 июня 2011

Другие в значительной степени ответили на вопрос, но я упомяну два момента, которые (я думаю) до сих пор не упоминались:

int i;

определяет i как int с мусором в нем (если i не является "глобальным"). Такой мусор может быть представлением ловушки , что означает, что его использование может быть "плохим":

Представление ловушки - это набор битов, который при интерпретации как значение определенного типа вызывает неопределенное поведение. Представления ловушек чаще всего встречаются на значениях с плавающей запятой и указателях, но в теории почти любой тип может иметь представления ловушек. Неинициализированный объект может содержать представление ловушки. Это дает то же поведение, что и старое правило: доступ к неинициализированным объектам приводит к неопределенному поведению.

Также int i; также может быть предварительным определением , что означает, что вы говорите компилятору: "i - это int, и я определю его позже. не, тогда определите это для меня. Вот очень хорошее объяснение , почему C имеет предварительные определения .

0 голосов
/ 05 июня 2011

Он делает то же самое, что и ваше предыдущее объявление:

  1. выделяет место в стеке для целого числа
  2. компилятор связывает имя с пробелом (ваша работающая программа не сделает этого обязательно)
  3. целое число не инициализировано.
...