Инициализация всех переменных в C в одной строке и неинициализированное значение
На языке Си, это
int x, y, z = 0;
То же самое, что и это?
int x = 0;
int y = 0;
int z = 0;
Также, если я просто скажу int a;
, кажется, что значение a
равно нулю, даже если оно неинициализировано, но не неопределенно, как описано в , каким будет значение неинициализированной переменной?
4 ответа:
Нет, эти два понятия не эквивалентны.
int x, y, z = 0;
В этой строке
Однако вы можете сохранить его в "одной строке" за цену некоторой многословности:x
иy
будут иметь неопределенное значение, в то время какz
инициализируется до нуля.int x = 0, y = x, z = y;
Теперь все три инициализируются одним и тем же значением (тем, которое вы дали
В качестве альтернативы, если вы находите предыдущий стиль некрасивым, вы можете заставить его работать в двух строках:x
). Чтобы инициализировать одну переменную другой, все, что требуется, - это предварительно определить инициализатор. И это работает, даже если он находится на той же линии. Вышеупомянутое также позволит вам довольно легко изменять начальное значение для всех переменных.Но теперь это назначение, а не инициализация.int x, y, z; x = y = z = 0;
Также, если я просто скажу
int a;
, кажется, что значениеa
равно нулю, даже если оно неинициализировано, но не неопределенно, как описано в том, каким будет значение неинициализированной переменной?"неопределенное значение" не имеет значения. значит "не-ноль". В нуле нет ничего, что делало бы его недопустимым кандидатом на начальное значение переменных. Некоторые" полезные " компиляторы нуль инициализируют переменные в отладочных сборках. Он может скрывать зловещие ошибки, если вы также не обращаете внимания на предупреждения компилятора.
Это:
int x, y, z = 0;
Не то же самое, что
int x = 0, y = 0, z = 0;
Или
int x = 0; int y = 0; int z = 0;
В первом случае инициализируется только
z
, а во втором - все три.Если значение не инициализировано, его значение является неопределенным, а чтение неинициализированной переменной - неопределенным поведением, и тот факт, что после чтения она имеет значение 0, является результатом неопределенного поведения.
Утверждение типа
int x, y, z = 0;
Инициализирует только последнюю переменную,
z
;x
иy
остаются неинициализированными.Возможный эквивалент
int x = 0; int y = 0; int z = 0;
Будет
int x, y, z; x = y = z = 0;
Что говорит,
Кроме того, если я просто скажу
int a;
, кажется, что значениеa
равно нулю, даже если оно неинициализированоЭто зависит от того, что если переменная имеет статическую длительность хранения, то она будет неявно инициализирована до 0.
Ответ на ваш первый вопрос- "нет", будет присвоена только явно инициализированная переменная. Остальные могут иметь любое значение (включая ноль).
Чтобы ответить на ваш второй (более интересный) вопрос (который, возможно, заслуживает отдельного вопроса):Термин "unitialized " просто означает, что ни одно значение не присваивается явно при создании экземпляра; значение-это все, что происходит в соответствующем месте памяти в это время. Некоторые среды заполняют стек с нулем в начале выполнения, поэтому в тривиальных примерах ноль вероятен. Однако это не будет верно все время, так как стек перетекает во время выполнения и содержит различные значения, оставшиеся от ранее выполненного кода.
Например, в следующем, вероятно, что
a
вfn()
не будет нулем для каждого вызова (или, возможно, любого вызова) и будет меняться между вызовами:void fn() { static int i = 1 ; volatile int a ; printf( "Call %d: a = %d\n", i, a ) ; i++ ; a = i ; } int main() { for( int i = 0; i < 10; i++ ) { fn() ; } }
В моем тесте (на ideone.com) он вывел следующее:
Call 1: a = 134513970 Call 2: a = 2 Call 3: a = 3 Call 4: a = 4 Call 5: a = 5 Call 6: a = 6 Call 7: a = 7 Call 8: a = 8 Call 9: a = 9 Call 10: a = 10
Как видите во втором и последующих вызовах он содержит все, что осталось в этом месте от предыдущего вызова, потому чтото же самое расположение стека используется повторно. Другой шаблон вызова-например, вставка вызова функции до или после
fn()
приведет к другому и менее предсказуемому результату, когда эта область стека будет повторно использоваться другими функциями. Например, когда я изменил тело цикла следующим образом:rand() ; fn() ;
В результате получилось:
Call 1: a = 1433091188 Call 2: a = 1433091188 Call 3: a = 1433091188 Call 4: a = 1433091188 Call 5: a = 1433091188 Call 6: a = 1433091188 Call 7: a = 1433091188 Call 8: a = 1433091188 Call 9: a = 1433091188 Call 10: a = 1433091188