在C中声明堆栈上的数组(VS2015)

在C中声明堆栈上的数组(VS2015),c,arrays,visual-studio,gcc,clang,C,Arrays,Visual Studio,Gcc,Clang,在C中尝试在堆栈上声明数组时遇到了一个奇怪的问题。我一直认为(至少到现在为止)如果没有常量表达式,在堆栈上声明数组是不可能的。例如,尝试在Windows上的VS2015上编译以下代码: int main() { int i = 3; int test[i]; return 0; } 生成一个“表达式必须有一个常量值”错误,这是我所期望的,但是在Linux机器上使用gcc和clang编译相同的代码是可行的。起初我认为可能是编译器推断出了一些东西,所以我尝试了以下方法:

在C中尝试在堆栈上声明数组时遇到了一个奇怪的问题。我一直认为(至少到现在为止)如果没有常量表达式,在堆栈上声明数组是不可能的。例如,尝试在Windows上的VS2015上编译以下代码:

int main()
{
    int i = 3;
    int test[i];

    return 0;
}
生成一个“表达式必须有一个常量值”错误,这是我所期望的,但是在Linux机器上使用gcc和clang编译相同的代码是可行的。起初我认为可能是编译器推断出了一些东西,所以我尝试了以下方法:

int main()
{
    int i = 3;
    int j = i*i;
    int test[j];

    return 0;
}
int main()
{
    int i = getchar();
    int test[i];

    return 0;
}
VS2015再次抱怨同样的错误,但gcc和clang编译的很好!我立刻想,好吧,也许那些编译器也在推断,毕竟,这只是“常量”表达式。因此,我尝试了以下方法:

int main()
{
    int i = 3;
    int j = i*i;
    int test[j];

    return 0;
}
int main()
{
    int i = getchar();
    int test[i];

    return 0;
}
当然编译器不能推断出这一点,当用于声明
测试
时,
i
的值只能在运行时知道,但令我惊讶的是,VS2015再次抱怨,但gcc和clang编译了它。。。 甚至添加以下内容:

int main()
{
    int i = getchar();
    int test[i];

    printf("%d\n", sizeof(test) / sizeof(int));

    return 0;
}
在ASCII表格中输入字符
x
,其值为120,输出120

发生了什么事?

您遇到了VLA(V可变-L长度Arrays)。
与“普通”数组不同,它们采用运行时确定的值作为大小说明符

由于VS2015主要支持C89,并且在C99中引入了VLA,因此Visual Studio不支持它们,因此发出了一个错误


注意VLA是C的一项功能。

这在技术上是可行的,因为数组位于堆栈顶部。但是我不打算使用这个特性
不初始化数组-
int test[i]={}会。我相信你的意思是“申报”。@molbdnilo谢谢,我会的edit@UnTraDe运用常识。你的4个例子都是完美的C,在过去的17年里一直如此。然而VisualStudio错误地向您提供错误和警告。有关来源,请参阅。直到2015年,他们才升级以支持1999年的标准。据我所知,支持还远远不够。VS不是一个好的C编译器,period.Correct。但请注意:此功能在C11中降级为可选功能。这里的总结:。@david.pfx:编译器从未被要求以特别有用的方式支持该功能。没有上下文(即使在顶层“main()”,其中需要一致的实现来保证任何特定大小的VLA分配(即使是单个元素)不会成功,也不会对一致性实现在失败情况下可能做的事情有任何限制。将它们放在一起,一致性编译器将被允许将任何分配VLA的尝试视为调用未定义的行为。高质量的编译器不应以这种方式运行,但……最好允许编译器拒绝编译器对他们无法有效运行的代码进行重新定义,而不是要求他们接受代码,但允许他们在执行代码时以任意方式进行操作。@supercat:就这样。另一种情况是“当时听起来是个好主意”但现在有助于某些人,也有助于混淆其他人。最好不要依赖于…。。@david.pfx:我希望标准的作者将更多的重点放在对某些但不是所有实现有用的结构上,并指定实现不需要支持这些结构,但必须拒绝它们不能支持的任何结构。IMHO,标准对于实现和程序,应编写定义“选择性一致性程序”,以便可以用C语言完成的大多数任务都可以用选择性一致性程序完成,但给出此类程序的任何一致性实现都需要在没有UB的情况下进行处理(注意。。。