为什么 case 语句中的标签应该是常量?
Why should labels in a case statement be constant?
在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 语句中使用变量值背后的意义是什么?
C++ 是从 C 发展而来的,其中 switch 语句被认为是 Jump Table (Branch Table)。要实现为跳转表,开关条件应该是恒定的,以便它可以很容易地转换为标签。
虽然标准从未规定应该如何实现 switch 语句,但最重要的是,case 标签应该能够在编译时对其进行评估。在 C 和 C++ 中,switch 语句计算表达式并将控制转移到计算为条件表达式值的许多 case 语句值之一。
6.4.2 switch语句[stmt.switch]
The switch statement causes control to be transferred to one of several statements depending on the value of a condition.
这种行为使其不同于其他支持 case 语句中的条件的语言。
对于实例,Javascript 将 switch ... case
语句描述为
The switch statement evaluates an expression, matching the expression's value to a case clause, and executes statements associated with that case.
所以你实际上是在尝试比较两个不同的构造并期望行为是相同的。
至于回答 the point behind this to not allowing variable values to be used in case statements?
,这会使 switch .. case
成为一个效率较低的构造,其中对于每个 iteration/instance,应重新评估案例标签以确定它是否匹配条件表达式。
C(而不是 C++)标准说:
C11: 6.8.4.2 开关语句 (p3)
The expression of each case
label shall be an integer constant expression and no two of the case
constant expressions in the same switch
statement shall have the same value after conversion.[...]
如果在 case
中允许使用表达式,则两个表达式可能具有相同的值。
C++(而不是 C)标准也是如此:
C++11:6.4.2 第 2 段:
[...] No two of the case constants in the same switch shall have the same value after conversion to the promoted type of the switch condition.
switch
/case
存在的原因(请记住 if
/else
存在于所有其他事物中)是为较低级别提供类似物"jump" 语法,以便您可以为您的代码创建快速、静态的“jump tables”。如果允许运行时表达式,这个原因就消失了。
问 为什么 switch
做这件事类似于问 if
为什么做另一件事,因此是空洞的。
仅仅因为你可以做某事并不意味着它就有意义。特别是,switch
不等同于 if/else
阶梯。
if/else
比 switch
更通用,后者旨在实现 "select the thing to do based on the value of the switch expression"。
练习 - 下面的代码会做什么?
var a = 5;
var b = 0;
switch(a)
{
case 5: b = 1; break;
case 5: b = 2; break;
case 1: b = 3; break;
}
现在 b
等于 2
还是 1
?如果它做两个分支,它不做 "select one thing to do",如果它做一个而不做另一个,它是任意决定。
将 case 值限制为常量表达式允许编译器对此代码发出错误。如果这些值可能会根据运行时的值而有所不同,编译器将无法验证两种情况是否具有相同的值,这是暂停问题的结果。
在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 语句中使用变量值背后的意义是什么?
C++ 是从 C 发展而来的,其中 switch 语句被认为是 Jump Table (Branch Table)。要实现为跳转表,开关条件应该是恒定的,以便它可以很容易地转换为标签。
虽然标准从未规定应该如何实现 switch 语句,但最重要的是,case 标签应该能够在编译时对其进行评估。在 C 和 C++ 中,switch 语句计算表达式并将控制转移到计算为条件表达式值的许多 case 语句值之一。
6.4.2 switch语句[stmt.switch]
The switch statement causes control to be transferred to one of several statements depending on the value of a condition.
这种行为使其不同于其他支持 case 语句中的条件的语言。
对于实例,Javascript 将 switch ... case
语句描述为
The switch statement evaluates an expression, matching the expression's value to a case clause, and executes statements associated with that case.
所以你实际上是在尝试比较两个不同的构造并期望行为是相同的。
至于回答 the point behind this to not allowing variable values to be used in case statements?
,这会使 switch .. case
成为一个效率较低的构造,其中对于每个 iteration/instance,应重新评估案例标签以确定它是否匹配条件表达式。
C(而不是 C++)标准说:
C11: 6.8.4.2 开关语句 (p3)
The expression of each
case
label shall be an integer constant expression and no two of thecase
constant expressions in the sameswitch
statement shall have the same value after conversion.[...]
如果在 case
中允许使用表达式,则两个表达式可能具有相同的值。
C++(而不是 C)标准也是如此:
C++11:6.4.2 第 2 段:
[...] No two of the case constants in the same switch shall have the same value after conversion to the promoted type of the switch condition.
switch
/case
存在的原因(请记住 if
/else
存在于所有其他事物中)是为较低级别提供类似物"jump" 语法,以便您可以为您的代码创建快速、静态的“jump tables”。如果允许运行时表达式,这个原因就消失了。
问 为什么 switch
做这件事类似于问 if
为什么做另一件事,因此是空洞的。
仅仅因为你可以做某事并不意味着它就有意义。特别是,switch
不等同于 if/else
阶梯。
if/else
比 switch
更通用,后者旨在实现 "select the thing to do based on the value of the switch expression"。
练习 - 下面的代码会做什么?
var a = 5;
var b = 0;
switch(a)
{
case 5: b = 1; break;
case 5: b = 2; break;
case 1: b = 3; break;
}
现在 b
等于 2
还是 1
?如果它做两个分支,它不做 "select one thing to do",如果它做一个而不做另一个,它是任意决定。
将 case 值限制为常量表达式允许编译器对此代码发出错误。如果这些值可能会根据运行时的值而有所不同,编译器将无法验证两种情况是否具有相同的值,这是暂停问题的结果。