转到标签后的变量声明

Kri*_*dra 66 c goto variable-declaration

今天我发现了一件有趣的事情.我不知道在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);
}
Run Code Online (Sandbox Code Playgroud)

给出错误

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.)
Run Code Online (Sandbox Code Playgroud)

那背后的逻辑是什么?我听说无法在switch的case语句中创建变量.由于JUMP是goto语句的同一范围(主要功能的范围,在我的情况)里面,我相信,范围是不是一个问题在这里.但是,为什么我会收到此错误?

Ste*_*non 84

语法根本不允许它.§6.8.1标签声明:

labeled-statement:
    identifier : statement
    case constant-expression : statement
    default : statement
Run Code Online (Sandbox Code Playgroud)

请注意,没有允许"标记声明"的子句.它不是语言的一部分.

当然,你可以通过一个空的陈述来解决这个问题.

JUMP:;
int a = 0;
Run Code Online (Sandbox Code Playgroud)


Bas*_*tch 14

你想在标签后面有一个分号,如下所示:

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

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


Pat*_* B. 6

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

t.c:7: error: a label can only be part of a statement and a declaration is not a statement
Run Code Online (Sandbox Code Playgroud)

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

  • 很高兴看到GCC正在改进其错误消息. (8认同)

COD*_*BOY 6

如果您知道为什么不能在 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
}
Run Code Online (Sandbox Code Playgroud)


jmo*_*eno 6

除了规范没有说明之外,简单的解释是编译器在goto之后编译代码,然后编译成一个可以计算偏移量的操作,并且因为你的变量声明不是一个声明而被踢/阻止它可以编译成这样的偏移量.