首页 > 解决方案 > 哪种有符号整数除法对应于位移?

问题描述

一个熟悉的事实是,在将整数除以 2 的幂时,一个好的编译器会将其强度降低为位移。

例如:

int main(int argc, char **argv) {
    return argc/2;
}

Clang -O2 将其编译为:

movl    %ecx, %eax
shrl    $31, %eax
addl    %ecx, %eax
sarl    %eax
retq

值得注意的是,虽然这个指令序列比实际的除法指令快得多,但它并不像人们希望的那样只是一个位移位。据推测,这是因为典型的 CPU 和 C 最终解决了截断除法(商轮趋向零),而这恰好与算术右移不完全匹配(并且需要降低强度以准确保留语义)。

哪种有符号整数除法与算术右移完全匹配?

标签: cbit-manipulationbit-shiftinteger-division

解决方案


在执行算术右移的情况下floor,2 的幂是匹配有符号整数右移的最合适的操作(向-inf舍入)。

请注意,有符号整数的右移是实现定义的。它可以是算术右移(由大多数众所周知的编译器实现)或逻辑右移。可以在此处找到有关这两种操作之间差异的更多信息。

算术右移示例:https ://godbolt.org/z/zhhfbc

#include <stdio.h>
#include <math.h>

int main(void)
{
    int val1 = 7;
    int val2 = -7;
    
    printf("Value1 = %.1lf\n", floor(val1/2.0));
    printf("Value2 = %.1lf\n", floor(val2/2.0));

    printf("Value1 = %d\n", val1 >> 1);
    printf("Value2 = %d\n", val2 >> 1);  

    return 0;
}

输出是:

Value1 = 3.0

Value2 = -4.0

Value1 = 3

Value2 = -4

推荐阅读