如果我有一个在标签后初始化的变量,为什么我会得到“标签只能是语句的一部分,而声明不是语句”?

我有以下简化代码:

#include <stdio.h>
int main ()
{
printf("Hello ");
goto Cleanup;
Cleanup:
char *str = "World\n";
printf("%s\n", str);
}

我得到一个错误,因为在标签后面声明了一个新变量。如果我将标签后面的内容(主要是初始化)放在{}块中,则编译成功。

我想我明白为什么在开关的情况下阻塞的原因,但为什么它应该适用于标签的情况?

此错误来自 gcc 编译器

181548 次浏览

这是 C 语法的一个怪异之处。标签(Cleanup:)不允许立即出现在 声明(如 char *str ...;)之前,只能出现在 声明(printf(...);)之前。在 C89中这并不是很困难,因为 声明只能出现在一个块的开头,所以你总是可以把标签往下移一点,避免这个问题。在 C99中,可以混合使用声明和代码,但是仍然不能在声明之前立即放置标签。

您可以在标签的冒号后面立即放置一个分号(正如 Renan 建议的那样) ,使得那里有一个空语句; 这就是我在机器生成的代码中要做的。或者,将声明提升到函数的顶部:

int main (void)
{
char *str;
printf("Hello ");
goto Cleanup;
Cleanup:
str = "World\n";
printf("%s\n", str);
return 0;
}

语言标准根本不允许这样做。标签后面只能跟语句,在 C 语言中,声明不能算作语句。解决这个问题的最简单方法是在标签后插入一个空语句,这样就不必像在块中那样跟踪作用域了。

#include <stdio.h>
int main ()
{
printf("Hello ");
goto Cleanup;
Cleanup: ; //This is an empty statement.
char *str = "World\n";
printf("%s\n", str);
}