未初始化数组的值在块范围内被覆盖
Values of uninitialized array being overwritten in block scope
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[]) {
int send_buf[4];
if(1){
int hello[5]={1,2,3,4,5};
}
for(int i=0; i<4; ++i)
printf("%d ",send_buf[i]);
printf("\n");
return 0;
}
输出: 1 2 3 4
在执行上述 C 代码时,输出总是导致分配给块范围内的数组 hello
的值。但是,如果在打印数组 send_buf
之前进行了任何引用(比如打印 send_buf
的地址),则输出结果通常是不确定的值。
有人可以解释一下为什么 send_buf
的内存已经分配到堆栈上时 send_buf
的值被覆盖了吗?
是否是某种 GCC 编译器优化延迟未初始化数组的分配直到它被引用?
使用 GCC 9.3.0 版编译。
当您不在 C 中(显式或隐式)初始化对象时,C 标准不保证它们具有任何固定值。它们的值可能会受到任何其他情况的影响,甚至可能会在每次使用时出现变化。
由于您没有初始化数组,编译器可能允许任何其他操作影响它。这可能包括允许 hello
的定义影响 send_buf
中出现的值。一个可能起作用的事实是编译器对值进行生命周期分析。例如,在如下代码中:
int p;
int q = 4;
printf("%d\n", q);
p = 3;
printf("%d\n", p);
编译器可能会发现,即使 p
是在 q
之前定义的,p
中永远不会同时有一个“活动”值,因为q
,因此编译器可以为 q
使用与 p
相同的内存。同样,编译器可能已经决定 send_buf
永远不会与 hello
同时包含活动值,因此它可以为 hello
使用与 send_buf
相同的内存.然后,由于您从未将值放入 send_buf
,因此从 hello
获取内存中的数据是您程序的一种可能行为。
要吸取的教训是,在各种情况下出现在数组中的“奇怪”值是它可能尚未初始化的线索,补救措施是对其进行初始化。
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[]) {
int send_buf[4];
if(1){
int hello[5]={1,2,3,4,5};
}
for(int i=0; i<4; ++i)
printf("%d ",send_buf[i]);
printf("\n");
return 0;
}
输出: 1 2 3 4
在执行上述 C 代码时,输出总是导致分配给块范围内的数组 hello
的值。但是,如果在打印数组 send_buf
之前进行了任何引用(比如打印 send_buf
的地址),则输出结果通常是不确定的值。
有人可以解释一下为什么 send_buf
的内存已经分配到堆栈上时 send_buf
的值被覆盖了吗?
是否是某种 GCC 编译器优化延迟未初始化数组的分配直到它被引用?
使用 GCC 9.3.0 版编译。
当您不在 C 中(显式或隐式)初始化对象时,C 标准不保证它们具有任何固定值。它们的值可能会受到任何其他情况的影响,甚至可能会在每次使用时出现变化。
由于您没有初始化数组,编译器可能允许任何其他操作影响它。这可能包括允许 hello
的定义影响 send_buf
中出现的值。一个可能起作用的事实是编译器对值进行生命周期分析。例如,在如下代码中:
int p;
int q = 4;
printf("%d\n", q);
p = 3;
printf("%d\n", p);
编译器可能会发现,即使 p
是在 q
之前定义的,p
中永远不会同时有一个“活动”值,因为q
,因此编译器可以为 q
使用与 p
相同的内存。同样,编译器可能已经决定 send_buf
永远不会与 hello
同时包含活动值,因此它可以为 hello
使用与 send_buf
相同的内存.然后,由于您从未将值放入 send_buf
,因此从 hello
获取内存中的数据是您程序的一种可能行为。
要吸取的教训是,在各种情况下出现在数组中的“奇怪”值是它可能尚未初始化的线索,补救措施是对其进行初始化。