我有一些简单的C ++代码:

#include <iostream>
int main(){
   {
     int a = 10;
     tag:
     std::cout << a << std::endl;
    }
     goto tag;
    return 0;
 }


现在,我知道使用goto并不是一个好主意,如果我将goto跳转到其他范围,则会出现编译错误。我已经尝试过了,这自然给了我一个明显的编译错误。但是我的问题是,这是否有可能进入某种无限循环

我问这个问题是因为question

最佳答案

我注意到问题中的代码是C ++代码而不是C代码。但是,这个问题在C和C ++中被双重标记,这令人讨厌,因为C和C ++的规则不同。

该代码无法在C ++中编译,但是等效的代码在C中编译

问题中的C ++代码不应编译。应该用C编写的类似代码可以编译,但是最终结果是无限循环。

C ++ 11

在ISO / IEC 14882:2011(C ++ 11标准;我没有要报告的2014年标准的正式副本)中,它表示:


  6.6.4 goto语句[stmt.goto]
  
  ¶1goto语句无条件地将控制权转移到由标识符标记的语句。标识符应为当前功能中的标签(6.1)。
  
  6.7声明声明[stmt.dcl]
  
  ¶1声明语句将一个或多个新标识符引入到一个块中;它具有声明形式:
  块声明
  如果先前在外部块中声明了由声明引入的标识符,则该外部声明对于该块的其余部分都是隐藏的,此后它将恢复其作用。
  
  ¶2具有自动存储持续时间(3.7.3)的变量在每次执行声明语句时都会初始化。在该块中声明的具有自动存储持续时间的变量在退出该块时被销毁(6.6)。
  
  ¶3可以转移到块中,但不能以初始化绕过声明的方式转移。如果程序的标量类型,带有普通构造函数和普通析构函数的类类型不具有标量类型,则从具有自动存储持续时间的变量不在范围内的点跳转到其范围内的点的程序会畸形87这些类型之一的cv限定版本,或者上述类型之一的数组,并且在没有初始化程序(8.5)的情况下声明。
  
  87)从switch语句的条件到case标签的转移在这方面被认为是跳跃。


尽管普通int是标量类型,但跳转绕过了初始化,因此是不允许的。

C11

在ISO / IEC 9899:2011(C11标准)中,它表示:


  6.8.6.1 goto语句
  
  约束条件
  ¶1goto语句中的标识符应为位于封闭函数中某处的标签命名。 goto语句不得从类型可变的标识符范围外跳到该标识符范围内。
  
  语义学
  ¶2goto语句导致无条件跳转到封闭函数中以命名标签为前缀的语句。


请注意,违反约束要求进行诊断。违反语义部分中的规则不需要诊断。

在附件一(通用警告)中,该附件是参考性的附件,而不是规范性的附件,它表示:


  —将具有自动存储持续时间的对象初始化的块跳入(6.2.4)。





  6.2.4对象的存储期限
  
  ¶5声明没有链接且没有存储类说明符static的对象的对象具有自动存储期限,某些复合文字也具有自动存储期限。尝试从与对象关联的线程之外的线程间接访问具有自动存储持续时间的对象的结果是实现定义的。
  
  ¶6对于没有可变长度数组类型的对象,其生存期从进入与之相关联的块开始,一直到该块的执行以任何方式结束。 (进入封闭的块或调用函数会挂起,但不会结束当前块的执行。)如果递归地输入该块,则每次都会创建该对象的新实例。对象的初始值不确定。如果为该对象指定了初始化,则每次在执行该块时到达声明或复合文字时都会执行该初始化;否则,每次到达声明时,该值将变得不确定。
  
  ¶7对于确实具有可变长度数组类型的对象,其寿命从对象的声明开始,直到程序执行离开声明的范围为止。35)如果递归地输入范围,则该对象的新实例每次创建一个对象。对象的初始值不确定。
  
  35)离开包含声明的最里面的块,或者跳到声明之前该块或嵌入块中的某个点,就离开了声明的范围。


请注意,问题代码中没有可变修改的类型(没有VLA或可变长度数组)。标准C ++不支持VLA的概念(尽管GNU C ++编译器允许将VLA作为扩展)。

代码(goto1.c):

#include <stdio.h>
int main(void)
{
    {
        int a = 10;
tag:
        printf("%d\n", a);
    }
    goto tag;
    return 0;
}


样本编译:

$ gcc -std=c11 -O3 -g -Wall -Wextra -Werror goto1.c -o goto1
$


这些是相当严格的警告选项,并且GCC不会发出窥视-鉴于C标准所说的,这是允许的行为。

09-30 13:05
查看更多