Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么在C/C+中交织switch/for/if语句是有效的+;?_C++_C_Language Lawyer - Fatal编程技术网

C++ 为什么在C/C+中交织switch/for/if语句是有效的+;?

C++ 为什么在C/C+中交织switch/for/if语句是有效的+;?,c++,c,language-lawyer,C++,C,Language Lawyer,我正在阅读boost/asio/coroutine.hpp,无法理解boost\u asio\u CORO\u重新输入和boost\u asio\u CORO\u产量的实现。扩展形式 reenter (this) { yield .. yield .. } 似乎是交织在一起的switch/if/for语句。我想知道为什么这是有效的C代码?我写了一些类似的东西(如下所示),发现它是用gcc编译的 int main() { int a = 1; switch (a) case

我正在阅读
boost/asio/coroutine.hpp
,无法理解boost\u asio\u CORO\u重新输入和boost\u asio\u CORO\u产量的实现。扩展形式

reenter (this) {
  yield ..
  yield ..
}
似乎是交织在一起的switch/if/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;
}
原因是它们不是结构化的控制流语句。相反,它们应该被视为静态分派的语法糖。分派意味着控制流被重定向,而静态意味着编译器知道它被重定向到哪里

所以你的代码

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标签,所以它们可以放在任何地方

从语法上讲,开关的主体只是一个语句(通常,但不一定是复合语句)

:

可能会贴上标签 :

例如:

switch(1) one: case 1: dothis();
如果它是复合语句,那么每个子语句也可以递归地标记。例如:

switch(x) {
    if(1) one: case 1: dothis();
    else case 0: orthis();  /*fallthru*/
    three: case 3: three();
}
语法将
大小写
/
默认
-标签和常规标签视为相同,只有语义检查验证
大小写
/
默认
-标签是否位于
开关

在实现方面,所有内容都编译成(平面)程序集

例如

被展平为(伪装配)

而且,没有理由不给这种平面代码中的任何东西贴上标签


代码>案例>代码> >代码>默认标签也像普通标签,除了它们通常也用于计算(通常)计算的跳。

这是一个骗局。如果你使用Boost,那么你在写C++,而不是C。所以你应该问为什么这是有效的C++,而不是为什么它是有效的C(即使答案可能非常相似)。。是否要包含一些原始代码?,这与此毫无关系。这是一个语法问题。不要乱贴标签。
switch(1) one: case 1: dothis();
switch(x) {
    if(1) one: case 1: dothis();
    else case 0: orthis();  /*fallthru*/
    three: case 3: three();
}
if(test) YesBranch; else ElseBranch;
IF_NOT_THEN_GOTO(test, PAST_YES_BRANCH)
YesBranch
goto PAST_NO_BRANCH;
NoBranch
PAST_NO_BRANCH:;