goto标签后的变量声明


72

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

编译以下代码

给出类似的错误

现在背后的逻辑是什么?我听说不能在switch的case语句内创建变量。由于JUMP处于goto语句的同一作用域内(在我的情况下为主要功能的作用域),因此我认为作用域在这里不是问题。但是,为什么我会收到此错误?

Answers:


93

语法根本不允许这样做。§6.8.1带标签的声明:

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

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


15

您需要在标签后加上分号,如下所示:

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


7

除了规范没有说明之外,简单的解释是,编译器认为goto之后的代码是某种可以编译为操作的代码,然后可以计算其偏移量,并且因为您的变量声明不是语句而开始执行/ block,它可以编译成这样的偏移量。


该标准(和gcc)允许在标签后加上复合语句,即JUMP: { int a = 0; printf("%d", a); };您是否认为这样的语句被编译成一个操作?
tbrk

6

我的gcc版本(4.4)出现此编译错误:

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


2

好吧,首先您应该保持一致。是LABELlabel。其次,标签是语句的一部分,并且声明对说明的回答不够。

您可以替换LABEL:label: ;,然后再进行编译。

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


对此感到抱歉。.已更改为JUMP,以免造成混淆。.请将此程序视为简单的测试程序,该程序可以重现我在这里要问的内容。这些printf语句毫无意义。
Krishnabhadra,2011年

没关系。printfs没什么意思,我不带s指出问题(和解决方案)printf
Michael Krelin-黑客2011年

大家都在说:1)标签必须是语句的一部分。而在C声明不是一个声明。2)错误与范围无关(这是我首先想到的),对吗?
Krishnabhadra,2011年

不,这与范围无关。
Michael Krelin-黑客2011年

1
是的,很有可能。由于跳转,绕过变量初始化可能会有不同的问题,但是您应该对此进行合理的诊断。如果这样做,只需将声明和初始化分开即可。
Michael Krelin-黑客

2

如果您知道为什么不能在switch的case语句中创建变量,那么基本上也是如此。作为解决方法,您可以尝试一下,


0
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.