Mil*_*lan 20 c scope loops shadowing
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");
}
}
Run Code Online (Sandbox Code Playgroud)
上面的代码生成以下输出:
Iteration 1 : 0 0
Iteration 2 : 0 5
Iteration 3 : 0 5
Iteration 4 : 0 5
Iteration 5 : 0 5
Run Code Online (Sandbox Code Playgroud)
我无法理解为什么printf迭代2,3,4,5中的第二个值是5.
我为什么第一个值在每个迭代是0的理解是,范围i在for环是局部的,但只要我们进入一个新的迭代的破坏i在被宣布for循环.
但我无法弄清楚为什么这个值在第二个时变为5 printf.
Bat*_*eba 53
程序的行为未定义.
内部范围在读取时i不会初始化.
(可能发生的事情是,重新引入i后续迭代占用与内部的前一个化身相同的内存,i第一次迭代的未初始化内存对应于0.但不要依赖于此.在其他情况下,编译器可能会吃你的猫.)
printf程序中的第二个是从未初始化的局部变量打印垃圾值i.通常情况下,行为未定义.
偶然地,代表您i(存储器单元或CPU寄存器)的存储位置在循环的每次迭代中是相同的.另一个意外,循环的主体作为每次迭代的单个复合语句执行(而不是展开循环并以交错方式同时执行所有迭代).另一个事故是,存储位置i保持其旧值不同于上一次迭代.因此,您正在打印的垃圾与循环的上一次迭代中该位置的最后存储值匹配.
这就是为什么你看到5在本地i上除了第一每次迭代.在垃圾值碰巧的第一次迭代0.
我想这就是发生的事情:
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)
Run Code Online (Sandbox Code Playgroud)