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

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

注1:这不是一个switch语句, 这个问题已在其他地方得到解答。

注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: } 

在标准中,它明确表示标签属于一个语句,因此标签之后的一个简单的分号( ; )可以规避您运行的问题,因为它被视为一个语句。

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

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

 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不是可选的。


  • open-std.org:n1124.pdf

你只需要写:

 label: ; 

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

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

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

标签应指向一个声明。

C强制要求:

(C99,6.8.1标记语句p4)“任何语句前面都可以有一个前缀,用于将标识符声明为标签名称。”

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

 void foo(void) { goto bla; bla: ; } 

空语句不执行任何操作。

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

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