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");
}
}
The above code generates the following output:
上面的代码生成以下输出:
Iteration 1 : 0 0
Iteration 2 : 0 5
Iteration 3 : 0 5
Iteration 4 : 0 5
Iteration 5 : 0 5
I'm not able to understand why the second printf
value in iterations 2,3,4,5 is 5.
我无法理解为什么迭代2,3,4,5中的第二个printf值是5。
My understanding of why the first value is 0 in each iteration is that the scope of i
in the for
loop is local and it is destroyed as soon as we go into a new iteration as i
was declared in the for
loop.
我对每次迭代中第一个值为0的原因的理解是for循环中i的范围是局部的,并且当我们进入新的迭代时它被销毁,就像我在for循环中声明的那样。
But I'm not able to figure out why this value becomes 5 at the second printf
.
但我无法弄清楚为什么这个值在第二个printf时变为5。
5 个解决方案
#1
53
The behaviour of your program is undefined.
程序的行为未定义。
The inner scope i
is not initialised at the point it's read.
内部范围i在读取时未初始化。
(What might be happening is that the reintroduced i
on subsequent iterations occupies the same memory as the previous incarnation of the inner i
, and the uninitialised memory on the first iteration corresponds to 0. But don't rely on that. On other occasions, the compiler might eat your cat.)
(可能发生的是,在后续迭代中重新引入的i占用与内部i的前一个化身相同的内存,并且第一次迭代中的未初始化的内存对应于0.但是不要依赖于此。在其他情况下,编译器可能会吃你的猫。)
#2
9
The second printf
in your program is printing garbage value from uninitialized local variable i
. In general case the behavior is undefined.
程序中的第二个printf是从未初始化的局部变量i打印垃圾值。在一般情况下,行为是未定义的。
By accident, storage location that represents your i
(memory cell or CPU register) is the same on each iteration of the cycle. By another accident, the body of your cycle is executed as a single compound statement for each iteration (as opposed to unrolling the cycle and executing all iterations at the same time in interleaved fashion). By yet another accident, the storage location of i
keeps its old value from the previous iteration. So, the garbage that you are printing matches the last stored value from that location on the previous iteration of the cycle.
偶然地,代表您的i(存储器单元或CPU寄存器)的存储位置在周期的每次迭代中是相同的。另一个意外,循环的主体作为每次迭代的单个复合语句执行(而不是展开循环并以交错方式同时执行所有迭代)。在另一次事故中,i的存储位置保留了之前迭代的旧值。因此,您正在打印的垃圾与循环的上一次迭代中该位置的最后存储值匹配。
That's why you see 5
in local i
on each iteration besides the first. On the first iteration that garbage value happened to be 0
.
这就是为什么除了第一次迭代之外,你在每次迭代中看到5个本地i。在垃圾值恰好为0的第一次迭代中。
#3
6
I think this is what is happening:
我想这就是发生的事情:
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
1
C compilers have some latitude in how they implement things and it would not be at all unusual for the local "i" to not actually be recreated each pass of the loop. It is likely actually only being created once, and re-used on each pass. In this case, your first print is outside the scope of the local variable so uses the i from outside the loop. The second print uses the local i as it is in scope, and after the first iteration has been set to 5. On the first iteration, the correct value is undefined, not 0, but the behavior of undefined is implementation specific, in your implementation it appears to automatically be initialized to 0.
C编译器在如何实现它们方面有一定的*度,并且本地“i”实际上不会在循环的每次传递中重新创建都不常见。它实际上可能只创建一次,并在每次传递时重复使用。在这种情况下,您的第一个打印超出了局部变量的范围,因此使用循环外部的i。第二个打印使用本地i,因为它在范围内,并在第一次迭代设置为5.在第一次迭代时,正确的值是未定义的,而不是0,但undefined的行为是特定于实现的,在您的实现中它似乎自动初始化为0。
#5
0
If you declare a local variable and don't give it a value before using it, if you get is undefined behavior.
如果声明一个局部变量并且在使用它之前没有给它一个值,那么如果你得到的是未定义的行为。
C standard say,
C标准说,
Variables with automatic storage duration are initialized each time their declaration-statement is executed. Variables with automatic storage duration declared in the block are destroyed on exit from the block.
每次执行声明语句时,都会初始化具有自动存储持续时间的变量。块中声明的具有自动存储持续时间的变量在从块退出时被销毁。
#1
53
The behaviour of your program is undefined.
程序的行为未定义。
The inner scope i
is not initialised at the point it's read.
内部范围i在读取时未初始化。
(What might be happening is that the reintroduced i
on subsequent iterations occupies the same memory as the previous incarnation of the inner i
, and the uninitialised memory on the first iteration corresponds to 0. But don't rely on that. On other occasions, the compiler might eat your cat.)
(可能发生的是,在后续迭代中重新引入的i占用与内部i的前一个化身相同的内存,并且第一次迭代中的未初始化的内存对应于0.但是不要依赖于此。在其他情况下,编译器可能会吃你的猫。)
#2
9
The second printf
in your program is printing garbage value from uninitialized local variable i
. In general case the behavior is undefined.
程序中的第二个printf是从未初始化的局部变量i打印垃圾值。在一般情况下,行为是未定义的。
By accident, storage location that represents your i
(memory cell or CPU register) is the same on each iteration of the cycle. By another accident, the body of your cycle is executed as a single compound statement for each iteration (as opposed to unrolling the cycle and executing all iterations at the same time in interleaved fashion). By yet another accident, the storage location of i
keeps its old value from the previous iteration. So, the garbage that you are printing matches the last stored value from that location on the previous iteration of the cycle.
偶然地,代表您的i(存储器单元或CPU寄存器)的存储位置在周期的每次迭代中是相同的。另一个意外,循环的主体作为每次迭代的单个复合语句执行(而不是展开循环并以交错方式同时执行所有迭代)。在另一次事故中,i的存储位置保留了之前迭代的旧值。因此,您正在打印的垃圾与循环的上一次迭代中该位置的最后存储值匹配。
That's why you see 5
in local i
on each iteration besides the first. On the first iteration that garbage value happened to be 0
.
这就是为什么除了第一次迭代之外,你在每次迭代中看到5个本地i。在垃圾值恰好为0的第一次迭代中。
#3
6
I think this is what is happening:
我想这就是发生的事情:
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
1
C compilers have some latitude in how they implement things and it would not be at all unusual for the local "i" to not actually be recreated each pass of the loop. It is likely actually only being created once, and re-used on each pass. In this case, your first print is outside the scope of the local variable so uses the i from outside the loop. The second print uses the local i as it is in scope, and after the first iteration has been set to 5. On the first iteration, the correct value is undefined, not 0, but the behavior of undefined is implementation specific, in your implementation it appears to automatically be initialized to 0.
C编译器在如何实现它们方面有一定的*度,并且本地“i”实际上不会在循环的每次传递中重新创建都不常见。它实际上可能只创建一次,并在每次传递时重复使用。在这种情况下,您的第一个打印超出了局部变量的范围,因此使用循环外部的i。第二个打印使用本地i,因为它在范围内,并在第一次迭代设置为5.在第一次迭代时,正确的值是未定义的,而不是0,但undefined的行为是特定于实现的,在您的实现中它似乎自动初始化为0。
#5
0
If you declare a local variable and don't give it a value before using it, if you get is undefined behavior.
如果声明一个局部变量并且在使用它之前没有给它一个值,那么如果你得到的是未定义的行为。
C standard say,
C标准说,
Variables with automatic storage duration are initialized each time their declaration-statement is executed. Variables with automatic storage duration declared in the block are destroyed on exit from the block.
每次执行声明语句时,都会初始化具有自动存储持续时间的变量。块中声明的具有自动存储持续时间的变量在从块退出时被销毁。