为什么 clang 会抱怨使用带有“-std=c99”标志的可变长度数组?

Rob*_*rtS 5 c c99 clang compiler-flags

当我编译这个实验代码时:

int main(void)
{
    int foo = 5;
    char bar[foo];
}
Run Code Online (Sandbox Code Playgroud)

使用 clang 和'-Weverything'单独的'-Wvla'标志或单独的标志与标志相结合'-std=c99',我仍然收到警告:

警告:使用可变长度数组 [-Wvla]

示例在这里

尽管与后来的 C 标准(C11、C18 等)相比,符合 C99 的实现将无一例外地支持可变长度数组,其中 VLA 支持是可选的。


  • 为什么我在使用带有'-std=c99'clang 标志的 VLA 时仍然收到此警告?
  • 这是一个错误还是只是为了提示注意遵守符合后来的 C 标准(以及 C89/C90)的实现?

Joh*_*ger 7

您是正确的,符合 C99 的实现必须支持 VLA,而实现可以符合更高版本的 C 标准而不支持 VLA。但我认为您只见树木不见森林:我认为上述标准之间的差异正是警告的重点。这并不是说您现在正在构建的代码可能会损坏。相反,它警告您所依赖的功能并非普遍向前兼容,因此如果您尝试在其他地方构建代码,那么它可能会中断。

如果 Clang 认为 VLA 是 C99 的非标准扩展,那么它根本不应该在-std=c99mode 中接受您使用 VLA 的代码。


Nat*_*dge 4

出于多种原因,人们可能希望避免在程序中使用可变长度数组,即使您所使用的语言版本保证支持它们。其一,正如约翰·博林格(John Bollinger)提到的,万一您想保持与不支持它们的其他标准的兼容性。

另一个问题是,在典型的基于堆栈的实现中,它们会消耗一定量的堆栈,这些堆栈在编译时可能不知道,或者不受信任的用户可能会影响,并且此类实现通常没有很好的方法来检测或从堆栈溢出中恢复。例如,Linux 内核开发人员因此决定不应在内核中使用 VLA,而使用-Wvla可以帮助他们强制执行此操作。

这些问题肯定不会适用于每个程序,这就是为什么该-Wvla选项是一个选项;如果出于某种原因您想了解程序中 VLA 的使用,则可以将其打开;如果不需要,则可以将其关闭。您选择使用-Weverything打开所有存在的警告。这个标志并不是真的对程序员有用,因为正如您所注意到的,它会打开许多​​警告,这些警告仅在某些情况下对那些知道自己需要它们的人有用。它的目的是帮助调试编译器本身。

因此,实际上,您已经告诉编译器“发出所有可能的警告,即使它们与我的情况无关”,现在您问为什么收到与您的情况无关的警告:- )