我想了解C中的switch() case:
语句
由编译器翻译成汇编程序操作码。
具体来说,我有兴趣了解这种差异
有一系列if then else
分支。
性能比较是主要议题。
关于词汇的几句话: 我熟悉汇编程序的主要概念,很久以前就用汇编程序编写了更简单的系统,但现在肯定没有关于x86汇编程序语义的东西。 因此直接汇编器输出将没有用。 伪代码是首选。
答案 0 :(得分:5)
根据编译器中的各种启发式方法,生成的代码最终可能只是一个简单的“if else if”语句链。在某些情况下,当案例的空间很小时,编译器可以创建一个跳转表,例如:
switch (foo) {
case 0:
a();
case 1:
b();
case 2:
c();
case 3:
d();
default:
e();
}
可以翻译成:
if (foo < 0 || foo > 3) goto label_default;
else goto internal_jump_table[foo];
internal_jump_table = { label_0, label_1, label_2, label_3 };
label_0: a();
label_1: b();
label_2: c();
label_3: d();
label_default: e();
还可以进行其他优化。编译器可以构建if语句的层次结构,以便二进制搜索正确的值,而不是检查是否相等。或者你可能有一堆值适当的跳转表和一些正常搜索完成的异常值。或者只是两个跳转表。
答案 1 :(得分:4)
编译器可以决定将其作为等效的if
/ else if
语句系列实现,或者可以决定使用branch table来优化它。这取决于几个参数,例如分支数量和最小范围的大小,包括您检查的所有值。
更新:我记得在某处读取通常编译器不打算创建分支表,除非至少有4个或更多的交换机案例;下面的Stephane Rouberol informative comment具体说明了如何为GCC配置此阈值。
答案 2 :(得分:2)
常见的反应总是“依赖于”。 性能可能取决于平台/ CPU类型,编译器,编译器选项等。
我认为,在适当的情况下,switch()
构造将具有复杂性log(n),其中n是case:
语句的数量。这是通过“二分搜索”实现的。
This page有很多细节(主要关注微软编译器,但我认为一般的想法一般适用)。
答案 3 :(得分:1)
考虑“{足够大”的switch cases
数量(足以让编译器选择生成分支表而不是简单的 if / else if ):
一个switch-case将有恒定时间(O(1))访问要执行的正确代码块,
虽然系列if/else if
语句将具有线性时间(O( n ),其中 n 是要评估的条件数({{ 1}}陈述),对于n&gt; =“足够大”)
更新:当然,这些注意事项不会考虑编译器优化!