可能重复:
为什么切换/案例而不是如果/否则如果?
我想了解编译器如何将switch() case:
C 中的语句翻译成汇编器操作码。
具体来说,我有兴趣了解一系列if then else
分支的区别。
性能比较是主要话题。
关于词汇的几句话:我熟悉汇编程序的主要概念,很久以前就为更简单的系统编写过汇编程序,但现在肯定对 x86 汇编程序语义一无所知。所以直接汇编输出将没有用。伪代码更受欢迎。
可能重复:
为什么切换/案例而不是如果/否则如果?
我想了解编译器如何将switch() case:
C 中的语句翻译成汇编器操作码。
具体来说,我有兴趣了解一系列if then else
分支的区别。
性能比较是主要话题。
关于词汇的几句话:我熟悉汇编程序的主要概念,很久以前就为更简单的系统编写过汇编程序,但现在肯定对 x86 汇编程序语义一无所知。所以直接汇编输出将没有用。伪代码更受欢迎。
根据编译器中的各种启发式方法,生成的代码最终可能只是一个简单的“if else if”语句链。在某些情况下,case空间较小时,编译器可以做一个跳转表,例如:
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 语句的层次结构来二进制搜索正确的值,而不是检查相等性。或者你可能有一堆适合跳转表的值和一些完成正常搜索的异常值。或者也许只是两个跳表。
共同的反应总是“取决于”。性能可能取决于平台/CPU 类型、编译器、编译器选项等。
我确实认为,在适当的情况下,switch()
构造将具有复杂性 log(n),其中 n 是case:
语句的数量。这是通过“二分搜索”实现的。
这个页面有很多细节(专注于微软的编译器,但我认为一般的想法适用)。
考虑“足够大”的数量switch cases
(足以让编译器选择生成分支表而不是简单的if / else if):
switch-case 将有恒定时间 (O(1)) 访问要执行的正确代码块,
而一系列if/else if
语句将具有线性时间(O(n),其中n是评估(if
语句)的条件数,因为n> =“足够大”)
更新:当然这些考虑没有考虑编译器优化!