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

时间:2015-04-25 15:19:52

标签: c++ c switch-statement

在JavaScript中,以下语句有效。

switch(true) {
    case a > b:
        max = a;
        break;
    case a < b:
        max = b;
        break;
    default:
       max = a;
}

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

现在我很想知道不允许在 case语句中使用变量值的原因是什么?

4 个答案:

答案 0 :(得分:32)

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

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

6.4.2 switch语句[stmt.switch]

  

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

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

对于实例,Javascript将switch ... case语句描述为

MDN switch

  

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

因此,您实际上是在尝试比较两种不同的构造,并期望行为是相同的。

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

答案 1 :(得分:15)

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

C11:6.8.4.2开关语句(p3)

  

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

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

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

C ++ 11:6.4.2第2段:

  

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

答案 2 :(得分:10)

switch / case存在的原因(请记住if / else存在于其他所有内容)是为较低级别的“跳转”提供模拟“语法,以便您可以为您的代码创建快速,静态的”jump tables“。如果允许运行时表达式,那么这个原因就会消失。

询问为什么 switch这件事情类似于问为什么if做了另一件事,因此是空的。

答案 3 :(得分:9)

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

if/elseswitch更通用,它旨在根据切换表达式&#34;选择要做的事情。

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

var a = 5;
var b = 0;
switch(a)
{
    case 5: b = 1; break;
    case 5: b = 2; break;
    case 1: b = 3; break;
}

现在b是否等于21?如果它同时执行两个分支,则它不会选择一个要做的事情,如果它做了一个而不是另一个,那么它就是任意的决定。

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