Я ожидал, что выражения "int i = 0" и "int i" будут одинаковыми.
Нет, это было неверное ожидание с вашей стороны.Если переменная объявлена вне функции (как «глобальная» переменная) или если она объявлена с ключевым словом static
, она гарантированно будет инициализирована равной 0, даже если вы не пишете = 0
.Но переменные, определенные внутри функций (обычные «локальные» переменные без static
), делают , а не имеют эту гарантированную инициализацию.Если вы не инициализируете их явно, они начинают содержать неопределенные значения.
(Обратите внимание, однако, что в этом контексте «неопределенный» не означает «случайный». Если вы пишете программу, которая использует или печатаетнеинициализированная переменная, часто вы обнаружите, что она начинается с одного и того же значения каждый раз, когда вы запускаете вашу программу. Случайно, это может быть даже 0. На большинстве машин происходит то, что переменная принимает любое оставленное значение "в стеке »предыдущей вызванной функцией.)
См. также следующие вопросы:
Инициализация нестатической переменной
Статическая переменнаяинициализация?
См. также раздел 4.2 и раздел 4.3 в эти примечания к классу .
См. также вопрос 1.30 в списке часто задаваемых вопросов C .
Приложение: на основе ваших комментариев звучит, как если бы вам не удалось инициализировать i
, неопределенное значениеэто случается сtart out с 0, поэтому ваш вопрос сейчас:
"Учитывая программу
#include <stdio.h>
int main()
{
int i; // note uninitialized
printf("%d\n", i); // prints 0
for(i++; i++; i++){
if(i>10) break;
}
printf("%d\n", i); // prints 1
}
, какую возможную последовательность операций может выдавать компилятор, который заставит его вычислить окончательное значениеиз 1? "
На этот вопрос может быть сложно ответить.Несколько человек пытались ответить на него, в другом ответе на этот вопрос и в комментариях, но по какой-то причине вы не приняли этот ответ.
Этот ответ снова: «Неинициализированная локальная переменная ведет к неопределенному поведениюНеопределенное поведение означает, что может произойти все что угодно. "
Важным в этом ответе является то, что в нем говорится, что" все может произойти ", а" все что угодно "означает абсолютно все .Это абсолютно не имеет смысла.
Второй вопрос, как я его сформулировал, на самом деле даже не имеет смысла, поскольку в нем есть внутреннее противоречие, потому что он спрашивает, «какая возможная последовательность операций могла быкомпилятор "излучает", но поскольку программа содержит неопределенное поведение, компилятор даже не обязан выдавать разумную последовательность операций вообще.
Если вы действительно хотите знать, какая последовательность операций у вашего компилятораиспуская, ты должен спросить это.Под Unix / Linux скомпилируйте с флагом -S
.Под другими компиляторами я не знаю, как просмотреть вывод на ассемблере.Но, пожалуйста, не ожидайте, что вывод будет иметь какой-то смысл, и, пожалуйста, не просите меня объяснить его вам (потому что я уже знаю, что это не имеет никакого смысла).
Поскольку компилятор разрешенчтобы что-то сделать, он может излучать код, как если бы ваша программа была написана, например, как
#include <stdio.h>
int main()
{
int i; // note uninitialized
printf("%d\n", i); // prints 0
i++;
printf("%d\n", i); // prints 1
}
«Но это не имеет никакого смысла!», говорите вы.«Как компилятор может превратить« for(i++; i++; i++) ...
»в просто« i++
»? И ответ - вы слышали это, но, возможно, вы все еще не совсем в это поверите - это когда программа содержит неопределенное поведение, компилятору разрешено делать что угодно .