在C中切换(){case:}性能

时间:2012-09-21 12:55:29

标签: c performance switch-statement

  

可能重复:
  Why Switch/Case and not If/Else If?

我想了解C中的switch() case:语句 由编译器翻译成汇编程序操作码。

具体来说,我有兴趣了解这种差异 有一系列if then else分支。

性能比较是主要议题。

关于词汇的几句话: 我熟悉汇编程序的主要概念,很久以前就用汇编程序编写了更简单的系统,但现在肯定没有关于x86汇编程序语义的东西。 因此直接汇编器输出将没有用。 伪代码是首选。

4 个答案:

答案 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; =“足够大”)

更新:当然,这些注意事项不会考虑编译器优化!