此问题在此处已有答案:
Variable declaration after goto Label(7个答案)
5天前关闭。
这篇文章是编辑并提交审查5天前.
我发现了一些在gcc下编译而不是在clang下编译的代码:
#include<stdio.h>
int main(int argc, char **argv) {
int test = 0;
if (test == 0) {
goto print_five;
} else {
return 0;
}
print_five:
int five = 6;
printf("value of five: %d\n", five);
return 0;
}
字符串
如果我声明变量five
到函数的顶部(在test
下),那么程序在两个编译器下都能编译。
在阅读了问题[1]和[2]之后,我想这可能与跳过变量声明有关,类似于需要在case语句中创建作用域。下面的示例也可以在两个编译器中编译。
print_five:
printf("value of five: ");
int five = 6;
printf("%d\n", five);
return 0;
print_five: ;
int five = 6;
printf("value of five: %d\n", five);
return 0;
的数据
然而,似乎情况并非如此,这与在标签后直接有一个表达式有关(也在问题[3]中解释过)。为什么这个例子可以用GCC编译而不能用Clang编译?
2条答案
按热度按时间osh3o9ms1#
在C99之前,所有的变量声明都必须在作用域块的顶部,因为声明不是语句:
字符串
从C99开始,你可以在函数的中间声明变量。这意味着在过去没有理由在声明之前写一个标签,显然标签从来没有被改变过允许放在声明之前(直到C23,下面更多)。有一些简单的修复方法:
型
或者:
型
GCC似乎是不兼容的,也就是说,编译它“不应该”编译的代码。将GCC设置为使用
-std=c99
甚至允许这样做,但是使用-pedantic
标志将给予警告。然而,Clang在这方面似乎是标准兼容的,并且不会编译它(即使使用
-std=c2x
)。这实际上是C23中的一个特性,应该会在明年发布。我建议你在C23正式发布之前使用上面的一个工作回合。
Clang和GCC,不管是好是坏,都喜欢在默认情况下启用自己的扩展,这可以使代码在一个中编译,而不是另一个。
fsi0uk1n2#
例如,这是有效的:
字符串
但这不是:
型
当涉及到标签时,在C17和更早的版本中,标签后面只能跟一个语句,而不能跟一个声明。
在C23中,语法发生了变化,当标签是复合语句的一部分(即包含在
{}
中)时,它后面隐含着一个null语句,因此在该版本的标准中,允许标签后面紧接着一个声明。换句话说,在C23中:
型
是这样处理的:
型
GCC显然允许这种新语法作为扩展,即使不在C23模式下,而clang没有这种扩展。