76

今天我发现了一件有趣的事情。我不知道不能在 goto 标签之后声明变量。

编译以下代码

#include <stdio.h>
int main() {
    int x = 5;
    goto JUMP;
    printf("x is : %d\n",x);
JUMP:
    int a = 0;  <=== giving me all sorts of error..
    printf("%d",a);
}

给出错误,如

temp.c: In function ‘main’:
temp.c:7: error: expected expression before ‘int’
temp.c:8: error: ‘a’ undeclared (first use in this function)
temp.c:8: error: (Each undeclared identifier is reported only once
temp.c:8: error: for each function it appears in.)

现在这背后的逻辑是什么?我听说不能在 switch 的 case 语句中创建变量。由于 JUMP 在 goto 语句的同一范围内(在我的例子中是 main 函数的范围),我相信范围在这里不是问题。但是,为什么我会收到这个错误?

4

7 回答 7

99

语法根本不允许。§6.8.1 标记语句:

labeled-statement:
    identifier : statement
    case constant-expression : statement
    default : statement

请注意,没有允许“标记声明”的条款。它只是不是语言的一部分。

当然,您可以使用空语句轻松解决此问题。

JUMP:;
int a = 0;
于 2011-12-05T11:19:45.950 回答
17

您需要这样的标签后的分号:

 #include <stdio.h>
 int main() {
     int x = 5;
     goto JUMP;
     printf("x is : %d\n",x);
 JUMP: ;     /// semicolon for empty statement
     int a = 0; 
     printf("%d",a);
 }    

然后,您的代码可以正确编译为 C99 标准gcc -Wall -std=c99 -c krishna.c(我在 Debian/Sid/AMD64 上使用 GCC 4.6)。

于 2011-12-05T11:21:06.323 回答
7

简单的解释,除了规范说没有,是编译器期望 goto 之后的代码编译成一个操作,然后它可以计算偏移量,并且因为你的变量声明不是语句/block 它可以编译成这样的偏移量。

于 2011-12-05T19:11:25.880 回答
6

我的 gcc 版本(4.4)给出了这个编译错误:

t.c:7: error: a label can only be part of a statement and a declaration is not a statement

. 此错误消息说明了一切。

于 2011-12-05T11:14:23.257 回答
2

嗯,首先你应该保持一致。要么LABEL要么label。其次,标签是声明的一部分,声明没有充分回答描述。

您可以替换LABEL:label: ;然后它更有可能编译。

编辑:现在您已经全面编辑了代码,应该将其JUMP:替换为JUMP: ;;-)

于 2011-12-05T11:13:41.633 回答
2

如果你知道为什么你不能在 switch 的 case 语句中创建变量,那基本上也是你不能这样做的原因。作为修复,你可以试试这个,

#include <stdio.h>
int main() {
    int x = 5;
    goto JUMP;
    printf("x is : %d\n",x);
JUMP:
    {                                              //Note this
       int a = 0;  // <=== no more error..
       printf("%d",a);
    }                                             //Note this
}
于 2011-12-05T11:24:44.110 回答
0
#include <stdio.h>
int main() {
    int x = 5;
    goto JUMP;
    printf("x is : %d\n",x);
JUMP:
    printf("Do anything after label but dont declare 
    anything. even empty statement will also work 
    because label can only be part of a statement");
    int a = 0;  
    printf("%d",a);
}
于 2011-12-05T12:23:34.217 回答