C 哪种有符号整数除法对应于位移位?

C 哪种有符号整数除法对应于位移位?,c,bit-manipulation,bit-shift,integer-division,C,Bit Manipulation,Bit Shift,Integer Division,一个熟悉的事实是,当整数除以二的幂时,一个好的编译器会将其强度降低为位移位 例如: 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

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

例如:

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最终都选择了截断除法(商向零舍入),而这恰好与算术右移不匹配(需要进行强度缩减以精确保留语义)


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

如果执行了算术右移,则按2的幂进行的
floor
是匹配有符号整数右移(向-inf舍入)的最佳操作

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

算术右移的示例:


换句话说,舍入到负无穷大。@NateEldredge可能舍入到最接近的整数会是一个更好的措辞。@AlexLop。不,正确的术语是向-inf舍入,
#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