关于语言不可知:为什么switch语句而不是if-else?

Why the switch statement and not if-else?

我已经想了一段时间了。到目前为止,我还不是一个核心程序员,主要是小型的Python脚本,我已经编写了一些分子动力学模拟。对于真正的问题:switch语句的意义是什么?为什么你不能只用if-else语句?

谢谢你的回答,如果之前有人问过这个问题,请指给我链接。

编辑

S.Lott指出,这可能是if/else与switch问题的重复。如果你想关闭,那么就这样做。我会让它继续讨论。


switch结构更容易转换为跳转(或分支)表。这可以使switch语句比case标签紧密结合时的if-else更有效。其思想是在内存中按顺序放置一组跳转指令,然后将值添加到程序计数器中。这将用添加操作替换一系列比较指令。

下面是一些非常简化的psuedo组装示例。首先,if-else版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    // C version
    if (1 == value)
        function1();
    else if (2 == value)
        function2();
    else if (3 == value)
        function3();

    // assembly version
    compare value, 1
    jump if zero label1
    compare value, 2
    jump if zero label2
    compare value, 3
    jump if zero label3
label1:
    call function1
label2:
    call function2
label3:
    call function3

接下来是交换机版本:

1
2
3
4
5
6
7
8
9
10
11
12
    // C version
    switch (value) {
    case 1: function1(); break;
    case 2: function2(); break;
    case 3: function3(); break;
    }

    // assembly version
    add program_counter, value
    call function1
    call function2
    call function3

您可以看到生成的程序集代码更加紧凑。请注意,需要以某种方式转换该值以处理除1、2和3之外的其他值。然而,这应该说明这个概念。


开关可以通过编译器进行优化-您将获得更快的代码。此外,我发现它在处理可枚举类型时更优雅。

总而言之,switch语句为您提供了性能+代码优雅:)

以下是一些有用的链接:

  • C中开关与if/else的速度比较#
  • 反馈导向开关语句优化(描述开关语句优化的pdf)


我忽略了通常不重要的这类低级优化,可能不同于编译器。

我认为主要的区别是可读性。if/else非常灵活,但是当您看到一个开关时,您马上就会知道所有的测试都是针对同一个表达式的。


为了便于表达,switch/case语句允许您将多个案例组合在一起,例如:

1
2
case 1,2,3: do(this); break;
case 4,5,6: do(that); break;

为了提高性能,编译器有时可以将switch语句优化为跳转表。


除了在.NET中提到的代码可读性和优化之外,您还可以打开枚举等功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
enum Color { Red, Green, Blue };

Color c = Color.Red;

switch (c) // Switch on the enum

{

// no casting and no need to understand what int value it is

case Color.Red:    break;
case Color.Green:  break;
case Color.Blue:   break;

}

通过几个案例(故意漏掉break语句)的能力是有用的,正如一些人已经说过的,它也更快。也许最重要也是最不重要的考虑是,它只会使代码比if/else更漂亮。:)


某些编译器可以"更好地"优化开关。在某些语言中使用switch语句存在缺陷。在Java中,交换机不能处理字符串,而在VB2005中,切换语句将无法使用单选按钮。开关可以更快更容易阅读,如果是通用的,将在更多的地方工作。


只有当事例值是常量(而不是动态的或派生的)并且事例数明显大于将哈希计算到查找表中的时间时,时间开关才能更快。

Javascript编译为在大多数引擎(包括Chrome的V8引擎)上执行的程序集,其实例是,在常见情况下,switch语句的执行速度要慢30%-60%:http://jspef.com/switch-if-else/20