Goto 标签后的变量声明

今天我发现了一件有趣的事情,我不知道不能在 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 函数的作用域)相同,所以我认为作用域在这里不是问题。但是,为什么我会得到这个错误呢?

31338 次浏览

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

您可以将 LABEL:替换为 label: ;,然后就可以编译了。

编辑: 现在您已经完全编辑了您的代码,它应该由 JUMP: ;替换为 JUMP:; -)

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

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

。这个错误消息说明了一切。

语法根本不允许这样做。6.8.1标签语句:

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

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

当然,您可以使用空语句来解决这个问题。

JUMP:;
int a = 0;

你需要在标签后面加上这样的分号:

 #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);
}

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

如果你知道为什么你不能在 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
}
#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);
}

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