为什么在 C/C++ 中交织 switch/for/if 语句是有效的?
Why it is valid to intertwine switch/for/if statements in C/C++?
我正在阅读boost/asio/coroutine.hpp
,无法理解BOOST_ASIO_CORO_REENTER和BOOST_ASIO_CORO_YIELD的实现。扩展形式
reenter (this) {
yield ..
yield ..
}
似乎是交织在一起的开关/如果/for 语句。我想知道为什么这是有效的 C 代码? 我写了类似的东西(如下所示(,发现它是使用 gcc 编译的。
int main() {
int a = 1;
switch (a)
case 0: if (1) a = 2;
else case 1: for (;;) {
case 3:
break;
}
return 0;
}
原因是 switch 语句不是结构化控制流语句。相反,它们应被视为静态调度的句法糖。调度意味着控制流被重定向,静态意味着编译器知道它被重定向到哪里。
所以你的代码
int a = 1;
switch (a)
case 0: if (1) a = 2;
else case 1: for (;;) {
case 3:
break;
}
return 0;
将被编译成大致等效的东西
int a = 1;
void *dest = dispatch(a, { case0_addr, case1_addr, case3_addr });
goto *dest;
case0_addr:
if (1) {
a = 2;
} else {
case1_addr:
for (;;) {
case3_addr:
goto case_end;
}
}
case_end:
return 0;
其中dispatch
是编译器运行的函数,用于发出静态调度所需的机器代码。由于所有调度值都是常量,并且编译器知道所有调度目标,因此它可以生成非常有效的机器代码。
至于为什么它是合法的,我想原因是因为它没有特别的理由是非法的。如图所示,case
语句只是 goto 标签,因此它们可以放置在任何位置。
语法上,开关的主体只是一个语句(通常,但不一定是复合语句(
6.8:
statement:
labeled-statement
compound-statement
expression-statement
selection-statement
iteration-statement
jump-statement
可以标记 6.8.1:
labeled-statement:
identifier : statement
case constant-expression : statement
default : statement
例:
switch(1) one: case 1: dothis();
如果是复合语句,那么每个子语句也可以递归地标记。例:
switch(x) {
if(1) one: case 1: dothis();
else case 0: orthis(); /*fallthru*/
three: case 3: three();
}
语法将case
/default
标签和常规标签视为相同,只有语义检查验证case
/default
-label是否在switch
内。
在实现方面,一切都编译成(平面(程序集。
例如
if(test) YesBranch; else ElseBranch;
被展平成(伪程序集(
IF_NOT_THEN_GOTO(test, PAST_YES_BRANCH)
YesBranch
goto PAST_NO_BRANCH;
NoBranch
PAST_NO_BRANCH:;
而且没有理由不能标记这种平面代码中的任何内容。
case
/default
标签也与常规标签一样,只是它们也用于(最常见的(计算跳转。
相关文章:
- 我的简单if-else语句是如何无法访问的代码
- Insert函数不适用于2 if语句C++
- If语句未被求值C++
- C++嵌套if语句,基本货币交换
- 多个If语句与使用逻辑运算符计算条件的单个语句的比较
- 是否可以使用if constexpr删除控制流语句
- 我似乎对if/else的基本语句有问题:/
- If语句在c++中被忽略
- 比较if语句中的数组值和int值
- 以在Qt中的IF语句中设置时间延迟
- Craps游戏问题,忽略if语句
- c++:定义if语句中的模板
- C++嵌套的 If 语句中,它无法按预期工作
- 如果中的多个语句是否与多个 if 相同?
- C++ If/Else 语句被跳过
- 使用语句if时逻辑的问题
- 如何添加语句if-else
- 如何将语句if(isalpha(c))从c++转换为MIPS ?
- 在if语句if C++中创建对象时出现作用域问题
- if语句-if/else和参数放置C++