Подтвердить что ты не робот

Почему эта программа создает нечетный вывод, когда переменная неинициализирована?

int main() {
    int j = 0;
    int i = 0;
    for (j = 0; j < 5; j++) {
        printf("Iteration %d :  %d ", j + 1, i);
        int i;
        printf("%d", i);
        i = 5;
        printf("\n");
    }
}

Приведенный выше код генерирует следующий вывод:

Iteration 1 :  0 0
Iteration 2 :  0 5
Iteration 3 :  0 5
Iteration 4 :  0 5
Iteration 5 :  0 5

Я не могу понять, почему второе значение printf в итерациях 2,3,4,5 5.

Мое понимание того, почему первое значение равно 0 на каждой итерации, заключается в том, что область i в цикле for является локальной и уничтожается, как только мы переходим к новой итерации, когда объявлен i в цикле for.

Но я не могу понять, почему это значение становится 5 во втором printf.

4b9b3361

Ответ 1

Поведение вашей программы undefined.

Внутренняя область i не инициализируется в точке, которую она читает.

(Что может случиться, так это то, что повторно введенный i на последующих итерациях занимает ту же память, что и предыдущее воплощение внутреннего i, а неинициализированная память на первой итерации соответствует 0. Но don 't полагаться на это. В других случаях компилятор может съесть вашу кошку.)

Ответ 2

Второй printf в вашей программе печатает значение мусора из неинициализированной локальной переменной i. В общем случае поведение undefined.

Случайно место хранения, которое представляет ваш i (ячейка памяти или регистр CPU), одинаково на каждой итерации цикла. К другой аварии тело вашего цикла выполняется как единый составной оператор для каждой итерации (в отличие от разворачивания цикла и одновременного выполнения всех итераций в чередовании). По еще одной аварии место хранения i сохраняет свое прежнее значение от предыдущей итерации. Таким образом, мусор, который вы печатаете, соответствует последнему сохраненному значению из этого местоположения на предыдущей итерации цикла.

Вот почему вы видите 5 в локальном i на каждой итерации, кроме первой. На первой итерации значение мусора оказалось 0.

Ответ 3

Я думаю, что это то, что происходит:

Breakpoint 1, main () at abc.c:4
4       int j = 0;
(gdb) s
5       int i = 0;
(gdb)
6       for(j=0;j<5;j++){
(gdb) p &i
$23 = (int *) 0x7fff5fbffc04           //(1) (addr = 0x7fff5fbffc04) i = 0
(gdb) p i
$24 = 0                                              // (2) i == 0
(gdb) s
7           printf("Iteration %d :  %d ",j+1,i);
(gdb) p &i
$25 = (int *) 0x7fff5fbffc00            //(3) here compiler finds there is contention in variable 'i' and assigns the inner one which is in present scope. Now, when subroutines are called, the stack frame is populated with (arguments, return address and local variables) and this is when the inner 'i' was also got allocated in this inner loop block but not initialized yet and this is the reason i get garbage value in the first integration output.

(gdb) p i
$26 = 1606417440                          // (4)  Here i == 1606417440 (Garbage)
(gdb) s
9           printf("%d",i);
(gdb) s
10          i = 5;
(gdb) p &i
$27 = (int *) 0x7fff5fbffc00
(gdb) p i
$28 = 1606417440
(gdb) s
11          printf("\n");
(gdb) p &i
$29 = (int *) 0x7fff5fbffc00
(gdb) p i                                                //(5) after executing previous statement, now i == 5
$30 = 5
(gdb) 

Ответ 4

Компиляторы

C имеют некоторую широту в том, как они реализуют вещи, и было бы совсем не необычно, если бы локальный "i" фактически не воссоздавался каждый проход цикла. Скорее всего, он создается только один раз и повторно используется на каждом проходе. В этом случае ваш первый вывод выходит за пределы локальной переменной, поэтому он использует я из-за пределов цикла. Вторая печать использует локальный i, поскольку он находится в области видимости, и после первой итерации было установлено значение 5. На первой итерации правильное значение undefined, а не 0, но поведение undefined является специфичным для реализации, в вашей реализации он автоматически инициализируется 0.

Ответ 5

Если вы объявите локальную переменную и не дадите ей значение перед ее использованием, если вы получите поведение undefined.

C, скажем,

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