代码之家  ›  专栏  ›  技术社区  ›  Imyaf

在什么条件下,在组装时对“if”和“if-else”进行比较?

  •  1
  • Imyaf  · 技术社区  · 11 月前

    对于x86程序集,“cmp”指令设置了两个标志:“ZF”和“CF”,允许通过一次比较来确定两个整数是相等还是更大或更小。如何用C编写代码,以便对所有三种情况只进行一次比较?有6种选择:

    if (x > y) { /*code1*/ } else if (x < y) { /*code2*/ } else { /*code3*/ }
    
    if (x < y) { /*code2*/ } else if (x > y) { /*code1*/ } else { /*code3*/ }
    
    if (x > y) { /*code1*/ } else if (x == y) { /*code3*/ } else { /*code2*/ }
    
    if (x < y) { /*code2*/ } else if (x == y) { /*code3*/ } else { /*code1*/ }
    
    if (x == y) { /*code3*/ } else if (x < y) { /*code2*/ } else { /*code1*/ }
    
    if (x == y) { /*code3*/ } else if (x > y) { /*code1*/ } else { /*code2*/ } 
    
    2 回复  |  直到 11 月前
        1
  •  3
  •   Mike Nakis    11 月前

    通常,我们在C中做的是编写一个常规的if/else-if/else语句,并期望编译器对其进行优化。

    因此,如果编译器可以知道x和y都是不需要重新计算的简单值,我们可以用C编写以下代码:

    if( x > y )
        /* code1 */
    else if ( x < y )
        /* code2 */
    else // x == y
        /* code3 */
    

    生成的优化组件应大致如下:

        mov eax, [x]
        cmp eax, [y]
        jg code1
        jl code2
        /* code3 */
        jmp after
    code1:
        /* code1 */
        jmp after
    code2:
        /* code2 */
        jmp after
    after:
    

    请注意,在上述优化的程序集中,x和y的值只加载一次,只比较一次。

    以下是godbolt上的源代码和生成的程序集:

    https://godbolt.org/z/8YxT5Kh7P

    相关说明如下:

        cmp     eax, ebp
        jg      .L7
        jl      .L8
    

    (这里, eax 包含y,以及 ebp 包含x。)

    这是一个编写C代码的实践示例 期望 编译器以某种方式对其进行优化 依靠 然而,在许多情况下,编译器决定做我们可能没有预料到的不同事情。

    因此,如果你养成了检查编译器是否确实按照你的预期执行的习惯,那么有时要准备好感到惊讶。


    上述技术适用于问题中列出的所有6种情况,只要x和y是简单的值。

    如果x或y需要重新评估,那么这种技术就不再有效了,你需要一种不同的方法,例如:

    int d = x - y; //where x and y are not simple values
    if( d > 0 )
        /* code1 */
    else if ( d < 0 )
        /* code2 */
    else // d == 0, meaning that x == y
        /* code3 */
    

    请注意,变量 d 很可能被编译器完全优化掉,导致代码与上面显示的非常相似。

        2
  •  2
  •   jokn    11 月前

    我认为你应该让编译器决定最好的方法。因此,您应该选择最易读的选项。

    如果您不确定,也可以使用“编译器资源管理器”进行检查

    我在这里举了一个例子: https://godbolt.org/z/v81z3rfMa