c - 如何允许 `else-if` 之间的标签?

标签 c winapi gcc visual-c++ label

这是一个简单的例子(不依赖于特定平台):

#include <stdio.h>
int main()
{
    for(int i = 0; i < 3; ++i)
        if(i == 0) printf("1\n");
        else if (i == 1) goto checkfor2;
        else checkfor2: if(i == 2 || i == 1) printf("2\n");
}

直播wandbox .

我提出这个问题的原始 Windows 代码:

#include <Windows.h>
#include <stdbool.h>
main() //sample with Win32 API
{
    for (;;) //infinite loop for my main logic
        if (WaitForSingleObject(hEvent, 1) != WAIT_TIMEOUT, true) //#1 check for some event
            //oops set comma true to test this event code
        {
            //do something
            //but here it will loop infinte and wouldn't check for #3
            //so if something goes wrong I can't exit

            //so clever me did the following:

            goto checkforexit; //see label on #3 below
        }
        else if (WaitForSingleObject(hEvent2, 1) != WAIT_TIMEOUT) //#2 check for another event
        {
            //do something else
        }
        else checkforexit: /*wow in between else and if*/ if (GetAsyncKeyState(VK_BACK) & 0x8000 && GetAsyncKeyState(VK_CONTROL) & 0x8000) //#3 check for keyboard shortcut for exit
            exit(0); //termination code
}

令我感到惊讶的是,这会奏效 - 似乎原始的 else ifif 的标签都按预期工作 - 这怎么可能?

如果您在 C 标准中添加引号,我将不胜感激。

它同时适用于 gcc(在 wandbox 上测试过)和 MSVC。

最佳答案

标签实际上是if语句的一部分; if 语句被标记。

C 2018 6.8 将语句(C 语言形式语法中的标记)定义为以下之一:

  • 标签语句
  • 复合语句
  • 表达式语句
  • 选择语句
  • 迭代语句
  • 跳转语句

if … else 语句在 6.8.4 中定义为selection-statement 的选项之一:

  • if ( 表达式 ) 语句 else 声明

如您所见,else 之后是一个语句,而一个语句 可以是一个标签语句,其中一种形式是“identifier : statement”。 (其他形式对 switch 语句使用 casedefault 标签。)

这不是编译器的障碍,因为它只是将控制从 goto 语句转移到标签作为其控制流图的一部分,它已经包括跳转,例如从ifelse(因为如果 expression 为假,则跳过第一个 statement),从while 循环到开头,从 break 语句到 for 语句之外,甚至从 goto 语句开始到 whilefor 循环中的标签。通过构建通用控制流图,编译器能够处理任意控制流,而不关心“结构化编程”。结构化编程是一种帮助人类的工具,但软件可以在没有该工具的情况下处理任意情况。

您可以在很大程度上使用标签在函数内任意跳转,但是当您跳转到声明了可变长度数组或其他可变修改类型的范围时,就会出现问题。如果你这样做,C 标准没有定义行为,例如:

if (flag)
    goto label;
while (foo)
{
    int bar[n];
    label: // Error, delaration of `bar` is skipped.
    …
}

关于c - 如何允许 `else-if` 之间的标签?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63104328/

相关文章:

c++ - 为什么 GCC 会在显式指定模板参数时产生奇怪的错误并尝试调用错误的方法?

c - 谷歌云引擎的内存分配(C 编程)限制

c++ - g++ 和 clang++ 在结构/类特化中使用非类型参数的不同行为

java - 定时攻击C——由java改造而成

windows - 处理鼠标中键点击

c++ - 从 Windows 10 上的 Win32 GUI 应用程序输出到控制台

c++ - BitBlt 内存泄漏

c++ - 您的计算机中缺少 libgcc_s_sjlj-1.dll

c - 如何链接ELF32汇编和C文件?

c - 链表插入行为