c - 如何允许在“else-if”之间添加标签?
问题描述
这是一个简单的示例(不依赖于特定平台):
#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");
}
现场魔杖盒。
我提出这个问题的原始 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 if
和标签if
都按预期工作 - 这怎么可能?
如果您在 C 标准中添加报价,我将不胜感激。
它适用于 gcc(在 wandbox 上测试)和 MSVC。
解决方案
标签实际上是if
语句的一部分;声明被if
标记。
C 2018 6.8 将语句(C 语言形式语法中的标记)定义为以下之一:
- 标记语句
- 复合语句
- 表达式语句
- 选择陈述
- 迭代语句
- 跳转语句
if … else
语句在 6.8.4 中定义为选择语句的选项之一:
if
(
表达式)
语句else
语句
如您所见,后面else
是语句,语句可以是标签语句,其中一种形式是“<em>标识符:
语句”。(其他形式使用case
和default
标签作为switch
语句。)
这不是编译器的障碍,因为它只是将控制从goto
语句转移到标签作为其控制流图的一部分,其中已经包括诸如从if
到 的跳转else
(因为如果第一个语句被跳过表达式为假),从循环的结尾到while
循环的开头,从break
语句到语句外for
,甚至从语句到内部或循环goto
的标签。通过构建一个通用的控制流图,编译器能够处理任意控制流,而不关心“结构化编程”。结构化编程是一种帮助人类的工具,但软件可以在没有该工具的情况下处理任意情况。while
for
您可以在很大程度上使用标签在函数内部任意跳转,但是当您跳转到声明了可变长度数组或其他可变修改类型的作用域时会出现问题。如果您这样做,C 标准不会定义行为,例如:
if (flag)
goto label;
while (foo)
{
int bar[n];
label: // Error, delaration of `bar` is skipped.
…
}
推荐阅读
- php - Laravel:用户登录后抛出 MethodNotAllowedHttpException
- python - 需要将pandas相关高亮表(cmap Matplotlib)保存为png图片
- vim - 调用 vim 插件命令 :Foo 会自动重绘!之后(即执行 :Foo | redraw!)
- php - mysqli_fetch_array 和 foreach 的解释
- css - 如何在使用 css 悬停在另一个元素上时公开 div 元素
- python - 使用将列表转换为 Dataframe 时遇到“Py4JJavaError”
- go - Go 变量名中大写缩写后的大写
- matlab - 如何在matlab中将矩阵分配给另一个矩阵的对角线
- javascript - 使用 for 循环、数组和 eventListener 更改输入元素的“名称”属性 - 无 jQuery
- php - Codeigniter - 使用控制器和方法创建函数循环表单