为什么声明一个具有可变大小的C数组时没有出现编译错误?

6

我一直认为当我在堆栈上声明一个大小由变量或参数提供的数组时,应该会出现错误。

然而,我发现如果我不显式初始化数组(是的,它不会在堆栈上,但我想知道缺少错误的原因)。

例如,以下代码由于array2而无法编译:

#define N 30

void defineArrays(int n)
{
    int i,j;
    int array1[N] = {};

    int array2[n] = {};

    for(i=0; i<N; ++i) array1[i] = 0;

    for(j=0; j<n; ++j) array2[j] = 0;
}

但是以下代码可以编译和运行,即使我从主函数发送一个真正的n:
#define N 30

void defineArrays(int n)
{
    int i,j;
    int array1[N] = {};

    int array2[n];

    for(i=0; i<N; ++i) array1[i] = 0;

    for(j=0; j<n; ++j) array2[j] = 0;
}

我在这里缺少什么?是将array2声明为指针吗?我正在使用gcc。

更新:感谢所有回答的人。问题确实是我的gcc版本出了一些奇怪的问题,默认情况下使用C99(或许不太奇怪,也许只是我太老了),而我错误地认为它默认使用C90,除非我告诉它使用其他版本。

4个回答

14

C99引入了可变长度数组的能力,现在可在GCC中使用(尽管据报道并非完全符合标准)。在第二个示例中,您似乎正在利用该功能。

链接到GCC有关可变长度数组的信息:http://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html


该死,我没意识到gcc现在默认使用c99了。我已经太长时间使用g++了。 - Uri
@Uri 因为你使用了脏话,所以我不会给你的问题点赞。 - Alex

3

我认为你需要选择C标准版本。

gcc -fsyntax-only -std=c89 -pedantic -x c -

<stdin>: In function ‘defineArrays’:
<stdin>:6: warning: ISO C forbids empty initializer braces
<stdin>:8: warning: ISO C90 forbids variable length array ‘array2’

对比。

gcc -fsyntax-only -std=c99 -pedantic -x c -
<stdin>: In function ‘defineArrays’:
<stdin>:6: warning: ISO C forbids empty initializer braces

1

使用初始化程序声明数组会强制该数组为静态数组(在编译时创建),即使其作用域在函数内部。编译器无法在编译时定义数组,因为它此时不知道“n”的值。


我明白,但是为什么我能编译第二个? - Uri

1

当我用gcc编译第一个示例时,它给我返回了这个错误:

error: variable-sized object may not be initialized

我想这是不被允许的,因为你不知道变量n会有多大,所以你不能确定它是否足够大来容纳你试图初始化的所有元素。也就是说,假设你有如下代码:

int array2[n] = { 1, 2, 3, 4 };

这需要 array2 至少有 4 个插槽。如果传入零的话,会怎样呢?

第二个示例没有这个问题,因为您没有对 array2 的大小做任何隐含的陈述。

希望能帮到您,

Eric Melski


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接