可能有重复但无法找到相同的内容。
假设我有以下C
代码:
int a;
printf("Enter number :");
scanf("%d",&a); // suppose entered only an integer
// ignoring return value of scanf()
我有一个案例来检查a
是zero
还是non-zero
。
if(a)
printf("%d is non-zero",a);
else
printf("%d is zero",a);
使用if-else
一切都很好,我也知道if-else
的其他变体来实现这一目标。但问题来自于switch-case
,因为它说我们可以在switch-case
中实现我们可以在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;
}
但问题是,为什么?为什么if(a)
有效而case a:
不是? switch-case
是编译时操作还是if()
运行时?
答案 0 :(得分:9)
原因是switch
个案例可以实现为跳转表(通常使用无条件分支指令)。所以它们必须在编译时解决。
这使得它们比if
更快,所以最好在可能的情况下使用它们。
答案 1 :(得分:2)
案例表达式必须是常量。 a
是变量,因此不允许。 0
是常数,所以没关系。只允许常量表达式意味着编译器更容易优化代码。
if语句的条件表达式没有这样的约束。
答案 2 :(得分:1)
除了编译时/跳转表问题,if
和switch
不一样,即使case
接受变量,这两个代码也不会相同行为。当且仅当条件表达式导致非零值时才会计算if
body,而当且仅当控制表达式和标签具有相同值时才输入case
。
if-then-else
和switch
语句之间存在大的区别,请记住break
不是强制性的,并且执行属于所有case
如果什么都没有阻止它。这种行为与跳转表非常相似,因为在switch
执行内部只是在某处跳转并继续直到找到break
。但是这种用法很少见,但它比if-then-else
版本更有用,也更容易。
标准要求标签是编译时常量,正如其他人已经说过的那样,它背后的想法是性能的跳转表。即使它不是强制性的(C标准需要灵活),C99理由文件似乎证实了这一点:
形式的案例范围,lo .. hi,被认真考虑,但最终没有在标准中采用,理由是它没有增加任何新功能,只是编码方便有问题。这个结构似乎承诺的超出了它的强制要求:
可能会为无辜的案例范围(例如0 .. 65535)生成大量代码或跳转表空间。
范围'A'..'Z'将指定字符代码之间的所有整数 “大写字母A”和“大写字母Z”。在一些常见的字符集中这个范围 将包括非字母字符,而在其他字符中,它可能不包括所有字符 字母字符,尤指非英文字符集。
答案 3 :(得分:1)
正如其他人所说,这是语言定义的方式。
如果你有
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;
}
编译器无法预先弄清楚,在编译的时候应该去,如果它是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主要用于当您有很多选择时,但在构建代码时每个选项都是已知的。如果不是这样,你还需要别的东西。
答案 4 :(得分:1)
其他信息想要分享Wiki
If the range of input values is identifiably 'small' and has only a few gaps, some
compilers that incorporate an optimizer may actually implement the switch statement as
a jump table or an array of indexed function pointers instead of a lengthy series of
conditional instructions. This allows the switch statement to determine instantly what
branch to execute without having to go through a list of comparisons.
答案 5 :(得分:1)
这是该语言创作者的设计决定。 IF 案例标签是常量,编译器可以通过使用跳转表来优化某些情况。如果不是,代码将等同于多方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语句完全没有性能优势。另一方面,如果我们要求所有条件都是常数......