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

use*_*500 92 c gcc

我有以下简化代码:

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

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

我想在切换的情况下我理解阻塞的原因,但为什么它应该适用于标签?

此错误来自gcc编译器

Ren*_*ani 123

语言标准根本不允许.标签只能跟在语句后面,而声明不能算作C中的语句.解决这个问题的最简单方法是在标签后插入一个空语句,这样可以使你无法按照你需要的方式跟踪范围.在一个街区内.

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

  • 在C99之前,所有声明都必须在块中的所有语句之前,因此在声明上有标签是没有意义的.C99放宽了这个限制,允许声明和语句在一个块中混合,但是*labeled-statement*的语法没有改变. (27认同)
  • 哇,这很棒.这背后的原因是什么? (14认同)
  • 对于这种语言怪癖,通常不可能给*原因*.语法就是它的方式.我可以查看C Rationale文档......但直到明天......但我可能找不到任何东西. (4认同)
  • 这也是“case”语句中的一个问题。 (4认同)
  • @zwol 谢谢,你在哪个时区?我这样问是为了让我们知道您明天什么时候到,这样我们就可以给您打电话,以防您忘记。 (2认同)

zwo*_*wol 25

这是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;
}
Run Code Online (Sandbox Code Playgroud)