为什么case语句中的标签应该是常量?

fro*_*tto 24 c c++ switch-statement

在JavaScript中,以下语句有效.

switch(true) {
    case a > b:
        max = a;
        break;
    case a < b:
        max = b;
        break;
    default:
       max = a;
}
Run Code Online (Sandbox Code Playgroud)

但是在C/C++编程语言中,当我编写这个语句时,编译器给出了一个错误,表明case语句必须由常量值组成.有时在特殊情况下编写这样的switch-case语句会非常有用,但C/C++不允许我这样做.

现在我很想知道这背后有什么不允许在case语句中使用变量值?

Abh*_*jit 32

C++已经从C发展而来,其中switch语句被设想为跳转表(Branch Table).要实现跳转表,切换条件应该是常量,以便可以很容易地转换为标签.

虽然标准从不规定如何实现switch语句,但最重要的是,case标签应该能够在编译期间进行评估.在C和C++中,switch语句计算表达式并将控制转移到许多case语句值中的一个,这些值的计算结果为条件表达式的值.

6.4.2 switch语句[stmt.switch]

switch语句使控制权转移到多个语句之一,具体取决于条件的值.

此行为使其与支持case语句中的条件的其他语言不同.

至于一个实例,Javascript将switch ... case语句描述为

MDN切换

switch语句计算表达式,将表达式的值与case子句匹配,并执行与该case相关的语句.

所以你实际上是在尝试比较两种不同的构造,并期望行为是相同的.

至于回答the point behind this to not allowing variable values to be used in case statements?,这将使得switch .. case效率较低的构造,对于每个迭代/实例,应重新评估案例标签以确定它是否与条件表达式匹配.


hac*_*cks 15

C(而不是C++)标准说:

C11:6.8.4.2开关语句(p3)

每个case标签的表达式应为整数常量表达式,并且同一语句中的两个case常量表达式在switch转换后不得具有相同的值.[...]

如果允许表达式,case那么两个表达式可能具有相同的值.

C++(而不是C)标准说的相同:

C++ 11:6.4.2第2段:

[...]在转换为提升类型的开关条件后,同一开关中的两个外壳常数不应具有相同的值.

  • 这说明这是C/C++标准的精确选择!选择是避免对switch()指令中传递的每个值执行多个case!如果您有变量或操作的情况,那么肯定会有更多情况需要执行的情况!这种行为还允许一些编译器更好地优化指令! (3认同)

Lig*_*ica 10

其原因switch/ case存在(轴承在心中if/ else存在其他一切)是为较低级别的"跳跃"语法模拟,这样就可以创建快速,静态的" 跳转表为您的代码".如果允许运行时表达式,那个原因就会消失.

为什么 switch这个东西类似于问为什么if另一件事,因此是空洞的.


mil*_*bug 9

仅仅因为你可以做某事并不意味着有意义.特别是,switch不等同于if/else梯子.

if/else更通用的switch是"根据switch表达式的值选择要做的事情".

练习 - 以下代码会做什么?

var a = 5;
var b = 0;
switch(a)
{
    case 5: b = 1; break;
    case 5: b = 2; break;
    case 1: b = 3; break;
}
Run Code Online (Sandbox Code Playgroud)

现在b等于21?如果是两个分支,它不会做"中选择一个做的事情",如果它一个而不是其他,这是武断的决定.

将case值限制为常量表达式允许编译器对此代码发出错误.如果值可能因运行时的值而不同,则编译器无法验证两个案例是否具有相同的值,这是Halting问题的结果.

  • 至少有人知道switch语句在语义上不等同于一系列if/else语句.我曾经有人说使用switch语句进行"菜单/选项选择"类代码是"过早优化"而不是if/else梯形图(?!)因为(出于所有原因)没有足够的选择,这是痛苦的; +1 (3认同)