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

rwa*_*ace 3 c bit-manipulation bit-shift integer-division

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

例如:

int main(int argc, char **argv) {
    return argc/2;
}
Run Code Online (Sandbox Code Playgroud)

Clang -O2 将其编译为:

movl    %ecx, %eax
shrl    $31, %eax
addl    %ecx, %eax
sarl    %eax
retq
Run Code Online (Sandbox Code Playgroud)

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

哪一种口味符号整数除法的完全匹配算术右移?

Ale*_*op. 5

在执行算术右移的情况下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;
}
Run Code Online (Sandbox Code Playgroud)

输出是:

Value1 = 3.0

Value2 = -4.0

Value1 = 3

Value2 = -4
Run Code Online (Sandbox Code Playgroud)