C 为什么案例:始终需要常量表达式,而if()不';T
可能是重复的,但找不到相同的 假设我有以下C 为什么案例:始终需要常量表达式,而if()不';T,c,if-statement,switch-statement,C,If Statement,Switch Statement,可能是重复的,但找不到相同的 假设我有以下Ccode: int a; printf("Enter number :"); scanf("%d",&a); // suppose entered only an integer // ignoring return value of scanf() 我得到一个案例来检查a是零还是非零 if(a) printf("%d is non-zero",a); else printf("%d is zero"
C
code:
int a;
printf("Enter number :");
scanf("%d",&a); // suppose entered only an integer
// ignoring return value of scanf()
我得到一个案例来检查a
是零
还是非零
if(a)
printf("%d is non-zero",a);
else
printf("%d is zero",a);
使用if-else
一切都很好,我也知道if-else
的其他变体可以实现这一点。但问题来自于切换案例
,因为它说我们可以在切换案例
中实现所有我们可以在中执行的操作,如果其他操作
。但是下面的代码失败了
switch(a)
{
case a:
printf("%d is non-zero",a);
break;
default:
printf("%d is zero",a);
break;
}
另外,我知道在上面的代码中逆转这种情况,如下所示将起作用,我将有我的答案
switch(a)
{
case 0:
printf("%d is zero",a);
break;
default :
printf("%d is non-zero",a);
break;
}
但问题是,为什么?为什么
如果(a)
有效而案例a:
无效?switch case
是编译时操作,而if()
运行时?case表达式必须是常量a
是一个变量,因此不允许使用它0
是一个常数,所以这很好。只允许常量表达式意味着编译器更容易优化代码
if语句的条件表达式没有这样的约束。原因是
开关
案例可以实现为跳转表(通常使用无条件分支指令)。因此,必须在编译时解决这些问题
这使得它们比
if
更快,因此最好在可能的情况下使用它们。除了编译时/跳转表问题之外,if
和开关
不一样,即使case
接受一个变量,这两个代码也不会有相同的行为<当且仅当条件表达式产生非零值时,才会计算代码>如果正文;当且仅当控制表达式和标签具有相同值时,才会输入大小写
if-then-else
和switch
语句之间有很大的区别,请记住break
s不是强制性的,如果没有任何东西阻止它,则执行会通过所有的案例。这种行为实际上类似于跳转表,因为在开关中执行只需跳转到某个地方,然后继续执行,直到找到一个断点。然而,这种用法很少见,但它可能比if-then-else
版本更有用、更容易实现
该标准要求标签是编译时常量,正如其他人所说,其背后的思想是性能跳转表。即使不是强制性的(C标准需要灵活),C99基本原理文档似乎也证实了这一点:
表格的大小写范围,lo。。hi是经过认真考虑的,但最终没有在标准中采用,因为它没有添加新的功能,只是一种有问题的编码便利性。该结构似乎承诺了超出其授权范围的内容:
- 对于看似无辜的案例范围,例如0,可能会生成大量代码或跳转表。。65535
- “A”的范围Z'将指定的字符代码之间的所有整数
“大写字母A”和“大写字母Z”的大写字母。在某些常用字符集中,此范围
将包括非字母字符,在其他情况下可能不包括所有字符
字母字符,特别是在非英语字符集中
正如其他人所说,这是语言的定义方式
如果你有
int x, y, z;
int a;
... some code calculates x, y, z and a ...
switch(a)
{
case x:
.. do stuff here ...
break;
case y:
.. some more stuff ...
break;
case z:
... another bit of code ....
break;
}
编译器无法在编译时预先确定a应该在哪里,如果它是1、2、3、99、465或5113212。因此,这里的代码并不比我们的代码更有效
if (a == x) ... do stuff here ...
else if (a == y) ... some more stuff
else if (a == z) ... another bit of code
此外,如果x和y是相同的值,该怎么办。我们是想同时做一些事情和更多的事情来执行,还是只想做一件事——哪一件,第一件还是第二件。如果编译器重新对比较进行排序,使它们处于不同的顺序,因为这样效率更高,该怎么办
切换主要用于您有很多选择的情况,但在构建代码时,每个选择都是已知的。如果不是这样,你还需要别的东西 要共享的其他信息
如果输入值的范围可识别为“小”且只有几个间隙,则有些
包含优化器的编译器实际上可能会将switch语句实现为
跳转表或索引函数指针数组,而不是一系列冗长的
条件指令。这允许switch语句立即确定
无需经过比较列表即可执行分支。
这是语言创建者的设计决策。如果案例标签是常量,编译器可以通过使用跳转表来优化某些案例。如果不是,代码将与多路If语句等价,潜在的改进也就消失了
定义带有可变大小写标签的switch语句没有问题,甚至每个分支都有不同的条件,只是C的设计者没有这样做。可能是因为他们不认为这是他们正在编写的代码的优势
该构造存在于其他语言中,比如我有时使用的COBOL。在那里,出现退化版本并不罕见,如:
EVALUATE TRUE
WHEN x IS EQUAL TO 7
Do something
WHEN y IS LESS THAN 12
Do something else
WHEN z
Do yet another thing
END-EVALUATE
这里我们将if-else-if-else
链屏蔽为一个开关(EVALUATE),它通过按顺序计算条件,直到它匹配第一个值
在C语言中,设计者不希望这样,因为它与链式if语句相比,绝对没有性能优势。另一方面,如果我们要求所有条件都是常量…跳转表?使用常量表达式,开关可能被编译成跳转表。@DanielFischer:你明白我的意思了。。是的,我想要实现。如何实现if和case,以便只需要cons