为什么gcc/clang处理代码的方式略有不同?(举例说明)

为什么gcc/clang处理代码的方式略有不同?(举例说明),c,gcc,compiler-errors,clang,C,Gcc,Compiler Errors,Clang,所以我在玩C代码,我注意到了gcc和clang处理代码的方式 如果我在文件范围内使用可变大小声明数组,clang编译时不会出现问题,但gcc会抛出一个错误。我的猜测是,这与gcc/clang中默认启用/未启用哪些编译器标志有关,但如果有人能确切地告诉我为什么会发生这种情况,并可能建议一些在线资源,我可以从中了解有关此功能的更多信息,我将非常高兴 下面是抛出错误的任意代码示例- typedef struct node{ int data; struct node *next;

所以我在玩C代码,我注意到了gcc和clang处理代码的方式

如果我在文件范围内使用可变大小声明数组,clang编译时不会出现问题,但gcc会抛出一个错误。我的猜测是,这与gcc/clang中默认启用/未启用哪些编译器标志有关,但如果有人能确切地告诉我为什么会发生这种情况,并可能建议一些在线资源,我可以从中了解有关此功能的更多信息,我将非常高兴

下面是抛出错误的任意代码示例-

typedef struct node{
    int data;
    struct node *next;
    struct node *prev;
}node;

const int N = 1000;
node *table[N]; // This is where the error is

int main() {
    return 0;
在没有其他标志的情况下运行
clangexample.c
将编译良好的运行
gcc example.c
并没有其他标志将抛出错误-

example.c:9:7: error: variably modified 'table' at file scope
    9 | node *table[N];
      |       ^~~~

N
看起来像一个常数,但实际上不是。
const
表示«我发誓我不会更改此变量的值»(否则编译器会提醒我!)。 但这并不意味着它不能被另一种我在这个编译单元中看不到的方式改变;因此,这并不完全是一个常数

gcc
似乎对标准要求非常严格,但使用选项
-pedantic
会发出警告

$ clang -o prog_c prog_c.c -pedantic
prog_c.c:12:14: warning: variable length array folded to constant array as an extension [-Wgnu-folding-constant]
double table[N];
             ^
1 warning generated.

$ clang -o prog_c prog_c.c -pedantic -std=c90
prog_c.c:12:13: warning: variable length arrays are a C99 feature [-Wvla-extension]
double table[N];
            ^
prog_c.c:12:8: warning: size of static array must be an integer constant expression [-Wpedantic]
double table[N];
       ^
2 warnings generated.

$ clang -o prog_c prog_c.c -pedantic -std=c99
prog_c.c:12:8: warning: size of static array must be an integer constant expression [-Wpedantic]
double table[N];
       ^
1 warning generated.

根据您使用的
gcc
的版本,它默认为C90(带有一些扩展),并且可变长度数组不是C90的一部分

如果指定
-std=c99
-std=c11
,则应支持VLAs

但是,根据C语言定义,VLA不能具有
静态
存储持续时间(正如在文件范围中声明的数组那样)。因此,<代码> CLAN<代码>必须将代码< N>代码>作为常数表达式(非常类似C++),数组是固定长度的,不是可变长度的。不过,到目前为止,我还没有在
clang
文档中找到任何可以说明这一点的内容


使用选项
-std=c11-pedantic
运行两个编译器,查看是否没有相同的错误。

根据C标准,可变长度数组可能没有静态存储持续时间。但是,编译器可能有自己的语言扩展。此外,如果程序被编译成C++程序,则没有可变长度数组。更一般地,我认为Clang可能将静态已知的非易失性对象(包括在这里声明并在别处定义)作为编译时常数在其他上下文中处理,而不仅仅是数组维数。