二进制数据的运算成为位运算。操作符如下:
- "<<":左移运算,最高位左移到cf中,最低位为0。
- ">>":右移运算,最高位不变,最低位右移到cf中。
- "|":位或运算,在两个数的相同位上,只要有一个1,则结果为1。
- "&":位与运算,在两个数的相同位上,只有同时为1时,结果为1。
- "^":异或运算,在两个数的相同位上,当两个值相同为0,不同为1。
- "~":取反运算,将操作数每一位上的1变0,0变1。
代码
#include <stdio.h>
int main(int argc, char* argv\[\]){
argc = argc << 3;
argc = argc >> 5;
argc = argc | 0xffff0000;
argc = argc & 0x0000ffff;
argc = argc ^ 0xffff0000;
argc = ~argc;
unsigned int n = argc;
n <<= 3;
n >>= 5;
return 0;
}
这个是把无符号和有符号混在一起了
汇编
msvc
main(int, char**):
push %rbp
mov %rsp,%rbp
sub $0x30,%rsp
mov %ecx,0x10(%rbp)
mov %rdx,0x18(%rbp)
call 0x7ff746251817 ; <__main> shll $0x3,0x10(%rbp)
sarl $0x5,0x10(%rbp)
mov 0x10(%rbp),%eax
or $0xffff0000,%eax
mov %eax,0x10(%rbp)
andl $0xffff,0x10(%rbp)
mov 0x10(%rbp),%eax
xor $0xffff0000,%eax
mov %eax,0x10(%rbp)
notl 0x10(%rbp)
mov 0x10(%rbp),%eax
mov %eax,-0x4(%rbp)
shll $0x3,-0x4(%rbp)
shrl $0x5,-0x4(%rbp)
mov $0x0,%eax
add $0x30,%rsp
pop %rbp
ret
其他的编译器类似这个没有什么优化操作。在此只需要注意,右移运算有变化有符号数对应的指令为sar,可以保留符号位;无符号数不需要符号位,所以直接使用shr将最高位补0。