在C中为什么你需要一个goto标签后的声明?

时间:2012-03-16 02:07:56

标签: c gcc

我正在编写一些C代码,在我的代码中我有两个嵌套循环。在特定条件下,我想从内循环中break和外循环continue。我尝试使用外部循环代码末尾的标签来实现这一点,条件是goto该标签。但是gcc给出了一个错误,我在复合语句的末尾没有标签。为什么不呢?

注意1:这不是switch声明, 问题已被回答elsewhere

注2:这不是关于样式的问题,而是我应该或不应该使用goto语句或条件变量。

编辑:人们已经要求一个例子,我可以给出一个稍微简单的例子来检查数组是否是另一个数组的子数组

    int superArray[SUPER_SIZE] = {...}, subArray[SUB_SIZE] = {...};
    int superIndex, subIndex;

    for (superIndex=0; superIndex<SUPER_SIZE-SUB_SIZE; superIndex+=1)
    {
      for (subIndex=0; subIndex<SUB_SIZE; subIndex+=1)
        if (superArray[superIndex+subIndex] != subArray[subIndex])
          goto break_then_continue;

      // code that executes if subArray is a sub array

      break_then_continue:
    }

3 个答案:

答案 0 :(得分:38)

在标准中,它明确表示标签属于一个语句,因此标签之后的一个简单的分号(;)可以绕过你运行的问题,因为它算作一个声明。

6.8.3 / 6 中甚至有一个使用“ empty 1 语句的例子。

  

示例3 空语句也可用于携带标签   在复合陈述的结束之前

while (loop1) {
  /* ... */

  while (loop2) {
    /* ... */

    if (want_out)
      goto end_loop1;

    /* ... */
  }

  /* ... */

  end_loop1: ;
}

1 在标准中,这被称为null statement


  

6.8.1标记语句

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

请注意statement在上述引文中不是可选的。


答案 1 :(得分:4)

你只需要写:

label: ;

分号是一个空的陈述。你需要它,因为语言是这样定义的;你需要去发表声明,即使声明是空的。

    for (int i = 0; i < N; i++)
    {
        for (int j = 0; i < M; j++)
        {
            ...
            if (some_condition)
                goto continue_loop1;
            ...
        }
continue_loop1: ;
    }

你可以争论标签上的缩进。

答案 2 :(得分:4)

标签应指向一个声明。

C强制要求:

  

(C99,6.8.1标记陈述第4页)“   任何语句都可以在前缀之前将标识符声明为标签名称。“

在您的情况下,您可以使用空语句:

void foo(void)
{
    goto bla;

    bla:
    ;
 }

空语句不执行任何操作。

如果您有声明,也可以使用复合语句(块):

void foo(void)
{
    goto bla;

    bla:
    {
        int x = 42;
        printf("%d\n", x);
    }
 }