Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.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++ 为什么case语句中的标签应该是常量?_C++_C_Switch Statement - Fatal编程技术网

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

C++ 为什么case语句中的标签应该是常量?,c++,c,switch-statement,C++,C,Switch Statement,在JavaScript中,以下语句是有效的 switch(true) { case a > b: max = a; break; case a < b: max = b; break; default: max = a; } 开关(真){ 案例a>b: max=a; 打破 案例a

在JavaScript中,以下语句是有效的

switch(true) {
    case a > b:
        max = a;
        break;
    case a < b:
        max = b;
        break;
    default:
       max = a;
}
开关(真){
案例a>b:
max=a;
打破
案例a
但是在C/C++编程语言中,当我编写这个语句时,编译器给了我一个错误,显示case语句必须由常量值组成。有时在特殊情况下编写这样的switch-case语句会非常有用,但C/C++不允许我这样做


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

C++是从C演变而来的,其中switch语句被认为是一个函数。要实现为跳转表,开关条件应保持不变,以便可以轻松地将其转换为标签

尽管该标准从未规定如何实现switch语句,但最重要的是,case标签应该能够在编译时对其进行评估。在C和C++中,Switter语句计算表达式并将控制转移到许多条件语句值中的一个,该值计算条件表达式的值。 6.4.2开关语句[stmt.switch]

switch语句根据条件的值将控制转移到多个语句之一

这种行为使它不同于其他支持case语句中的条件的语言

例如,Javascript描述了
switch。。。case
语句为

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

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

至于回答
这个问题背后的要点是不允许在case语句中使用变量值?
,这将导致
切换。。case
一种效率较低的构造,对于每个迭代/实例,都应重新计算case标签,以确定其是否与条件表达式匹配。

C(而不是C++)标准规定:

C11:6.8.4.2切换语句(p3) 每个
case
标签的表达式应为整数常量表达式,同一
switch
语句中的
case
常量表达式中的任何两个在转换后都不得具有相同的值
[…]

如果在
案例中允许使用表达式,则两个表达式可能具有相同的值

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

C++11:6.4.2第2段: […]在转换为提升类型的开关条件后,同一开关中的两个case常量不得具有相同的值


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


问“为什么开关做这件事”类似于问“为什么开关做另一件事”,因此是空洞的。

仅仅因为你能做某事并不意味着这是有意义的。特别是,
开关
并不等同于
if/else
梯形图

if/else
switch
更一般,后者旨在“根据开关表达式的值选择要做的事情”

练习-下面的代码会做什么

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
?如果它同时执行两个分支,它就不会执行“选择一件要做的事情”,如果它执行一个而不是另一个,那就是任意的决定


将大小写值限制为常量表达式允许编译器对此代码发出错误。如果根据运行时的值,值可能不同,则编译器无法验证这两种情况是否具有相同的值,这是由于停止问题。

对不起,但是
开关(true)
的意义是什么?我不确定这是设计选择的原因还是结果,buy要求它们是常量,这样就可以将
switch
语句作为非常有效的编译时查找表来实现。@BetaCarotin-它检查是否有任何情况解析为
true
,我可以问你一个相反的问题:在case语句中允许使用变量值有什么意义?使用
if/else
ladder可以更清晰地编写代码。允许这种构造必须能够实现一些奇妙的代码混淆。如果每个
案例
都是在运行时评估的,想象一下使用副作用案例的可能性。温暖了我的心。谢谢你的回答,但是,你能给我一个关于跳转表的更多信息的链接吗?当然,如果情况不变,可以提供更有效的代码。但是有没有什么东西阻止编译器实现该语言的扩展版本,其中表达式不必是常量?我想这就是大多数新语言特性的开始。编译器可以在编译时决定表达式是否为常量,如果是常量,则可以提供更有效的代码。@kasperd:switch
switch
需要有效地实现分支表,如。将案例设置为非常量意味着对于一连串的“如果”语句来说是多余的。我不知道你暗示的是哪种现代语言不支持条件大小写,Ruby&Python don;我们不支持它,而且我们知道
javascript
没有做很多正确的事情<代码>Crockford
你在吗@