这是我的代码。首先要扫描2个数字m和n。然后扫描一个数字数组,即x[n]。第二行扫描的数字数应为n。但它不能正常工作。
#include <stdio.h>
int main()
{
int m = 0;
int n = 0;
int x[n];
scanf("%d", &m);
scanf("%d", &n);
for(int i = 0 ;i < n;i++)
{
scanf("%d", &x[i]);
}
}
它只扫描1个数字并跳出循环。我们应该有(i)s从0到n-1;
2条答案
按热度按时间px9o7tmv1#
这试图声明一个大小为零的可变长度数组,这已经是未定义的行为。
即使这(有一个零元素空间的VLA)在某种程度上是可能的,
...也是未定义的行为。
5f0d552i2#
让我试着解释一下考虑
x86_64
架构和gcc7.5x
编译器的代码行为。This answer和this answer的问题提供了堆栈在不同架构上的增长方向,对于
x86
来说,它是向下的,这意味着堆栈将从高内存地址增长到低内存地址(0xFF --〉0x 00)如果我们稍微修改你的代码,在运行时打印变量的地址和值,如图所示:
在
x86
上编译并运行上述代码后,我们可以注意到局部变量的地址是按降序分配的,如下所示,用于一个代码执行会话:如果你注意到
n
和x
的地址不同,它们是16-Bytes
,理想情况下它们应该在堆栈上是4-bytes
。但是,由于
int x[n]
被声明为0整数数组,因此理想情况下,它应该占用4字节的内存,即使底层编译器和体系结构机制将其视为4整数数组,并将其转换为4 integers * sizof(int) = 16-bytes
查看代码的进一步执行输出,我们可以看到,随着代码的进一步执行,地址
0x7ffdfb2b1700
处的n
的值被覆盖。请注意,代码对于
n < 5
的值将正常工作,因为对于n = 4
的值,循环将在n = 3
处终止,在这种情况下,n
的值将不会被覆盖,因为循环迭代为(n * sizeof(int)) ==> 3 * 4 = 12-bytes
:这就是为什么@DevSolar回答说这将导致未定义的行为。
我希望我能够提供一些澄清。