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 最终解决了截断除法(商向零舍入),而这恰好与算术右移不完全匹配(并且需要强度减少以完全保留语义)。
哪一种口味符号整数除法的将完全匹配算术右移?
在执行算术右移的情况下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)