Почему этот код C компилируется? - PullRequest
21 голосов
/ 13 июля 2010
#include <stdio.h>
int main() {
    int c = c;
    printf("c is %i\n", c);
    return 0;
}

Я определяю целочисленную переменную с именем c и присваиваю ее значение себе. Но как это можно скомпилировать? c не был инициализирован, так как его значение можно присвоить себе? Когда я запускаю программу, я получаю c is 0.

Я предполагаю, что компилятор генерирует код сборки, который назначает пространство для переменной c (когда компилятор встречает инструкцию int c). Затем он принимает любое ненужное значение в этом неинициализированном пространстве и присваивает его обратно c. Это то, что происходит?

Ответы [ 5 ]

30 голосов
/ 13 июля 2010

Я помню, как цитировал это в предыдущем ответе, но сейчас не могу его найти.

C ++ 03 §3.3.1 / 1:

Точкаобъявления для имени происходит сразу после его полного декларатора (пункт 8) и перед его инициализатором (если есть), ...

Следовательно, переменная c может использоваться даже до части инициализатора.

Редактировать: Извините, вы спрашивали о C конкретно;хотя я уверен, что там есть эквивалентная линия.Джеймс МакНеллис нашел его:

C99 §6.2.1 / 7: Любой идентификатор, который не является тегом структуры, объединения или перечисления, «имеет область действия, которая начинается сразу после завершения его объявления».За декларатором следует инициализатор.

11 голосов
/ 13 июля 2010

Ваше предположение совершенно верно. int c помещает пространство в стек для переменной, которая затем считывается и перезаписывается для части c = c (хотя компилятор может оптимизировать это). Ваш компилятор добавляет значение как 0, но это не всегда так.

5 голосов
/ 13 июля 2010

Неопределенное поведение - использовать неинициализированное значение (§C99 J.2 «Значение объекта с автоматической продолжительностью хранения используется, пока оно не определено»).Так что может случиться что угодно: от носовых демонов до c = 0, до игры в Nethack .

2 голосов
/ 13 июля 2010

Спецификация C не гарантирует, что переменные будут инициализированы в 0, 0.0, ни "", ни ".

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

Я всегда настраиваю IDE / Compiler на предупреждение об этом.

2 голосов
/ 13 июля 2010

c был инициализирован!

Хотя это одна строка кода, на самом деле он сначала инициализирует c, а затем присваивает ему c.Вам просто повезло, что компилятор инициализирует для вас c нулем.

...