为什么arr[3]产生与arr[SOME_CONST]不同的行为,其中SOME_CONST=3?

为什么arr[3]产生与arr[SOME_CONST]不同的行为,其中SOME_CONST=3?,c,C,我很难理解为什么要初始化具有文字大小的数组,例如int arr[3];,从初始化为int arr[SOME_CONST]等常量大小的数组中产生不同的行为;设置为3 当数组的大小作为文本提供时,它的行为与预期的一样: int-arr[3]; //初始化数组的前两个元素,不初始化第三个元素。 arr[0]=1; arr[1]=2; //打印数组的所有元素 printfarr[0]:%d\n,arr[0]; printfarr[1]:%d\n,arr[1]; printfarr[2]:%d\n,arr

我很难理解为什么要初始化具有文字大小的数组,例如int arr[3];,从初始化为int arr[SOME_CONST]等常量大小的数组中产生不同的行为;设置为3

当数组的大小作为文本提供时,它的行为与预期的一样:

int-arr[3]; //初始化数组的前两个元素,不初始化第三个元素。 arr[0]=1; arr[1]=2; //打印数组的所有元素 printfarr[0]:%d\n,arr[0]; printfarr[1]:%d\n,arr[1]; printfarr[2]:%d\n,arr[2]; 输出:

arr[0]: 1
arr[1]: 2
arr[2]: 0
正如您在输出中看到的,未初始化元素arr[2]的值与预期一样为0

当数组大小定义为常量时,该行为会变得异常,如下所示:

const int SOME_const=3; int arr[一些常数]; //初始化数组的前两个元素,不初始化第三个元素。 arr[0]=1; arr[1]=2; //打印数组的所有元素 printfarr[0]:%d\n,arr[0]; printfarr[1]:%d\n,arr[1]; printfarr[2]:%d\n,arr[2]; 输出:

arr[0]: 1
arr[1]: 2
arr[2]: 32766
现在,未初始化的元素arr[2]似乎有一个随机值32766

有人能帮我理解为什么这两种情况表现不同吗

我在ideone上创建了两个片段来演示这种行为


您使用什么编译器/系统?可能会将常量值放在主函数之外。通常这两种方法都会导致从堆栈中获取任意值。

C标准不保证局部变量的初始化

关于初始化声明:

arr[0] = 1;
arr[1] = 2;
编译器可以很好地将它们优化为以下语句:

int arr[3] = {1, 2, 0};
但是,对于这种情况,我不会依赖于一个编译器的行为。最好是在初始化语句中显式显示

你可以参考类似的讨论

在第二个场景中,您还尝试使用可变长度数组:

这是您正在使用的GCC编译器提供的扩展,我不建议在您的项目中使用它们

数组的长度在运行时计算,可能在堆栈上分配,具体取决于编译器实现

因此,它在代码中没有显式初始化

您可以在此处看到生成代码的示例:

我们不应该担心编译器在某些情况下的行为,除非 根据标准,这是不正确的


根据C标准,未初始化的局部变量可以有任何垃圾值。最好对它们进行初始化,不要依赖于编译器。

这些数组是本地分配给函数的,还是全局分配给函数的?两个代码段都在main中。关于:printfarr[2]:%d\n,arr[2];由于int-arr[3]的arr[2]元素;如果未初始化,则代码包含未定义的行为。以下是来自编译器的消息:untitled2.c:15:2:warning:“arr[2]”在此函数中未初始化使用[-Wuninitialized],编译时,始终启用警告,然后修复这些警告。对于gcc,至少使用:-Wall-Wextra-Wconversion-pedantic-std=gnu11注意:由于arr[2]项未初始化,其他编译器使用不同的选项来生成有关警告的消息,对printf的调用将显示该位置内存中的垃圾。这是编译器版本行:gcc版本4.8.5 20150623 Red Hat 4.8.5-36 GCCI在我的系统上尝试了您的代码。在这两种情况下,每次执行都会得到不同的结果。所以不要相信它是零。我试过gcc-7、gcc-8和gcc-10。