C语言的移位运算符

逻辑移位:

1.逻辑左移:高位丢弃,低位补0。对应的X86汇编指令:SAL(有符号数),SHL(无符号数)

2.逻辑右移:高位补0,低位丢弃。对应X86汇编指令:SHR

也就是说逻辑移位,移入的位都要补0。可见对于逻辑移位不考虑符号位。

算术移位:

1.算术左移:高位丢弃,低位补0。对应X86会变指令:SAL(有符号数),SHL(无符号数)

2.算术右移:高位补符号位,低位丢弃。对应X86会变指令:SAR

在C语言中的移位操作运算符都是算术移位,保证了符号位不变,相当于乘2和除2。

在进行移位操作时候,要小心,如果移位过多会出现错误。典型的几个数字是:溢出数,0,-1。

左移里一个比较特殊的情况是当左移的位数超过该数值类型的最大位数时,编译器会用左移的位数去模类型的最大位数,然后按余数进行移位,如:
int i = 1, j = 0x80000000; //设int为32位
i = i << 33;   // 33 % 32 = 1 左移1位,i变成2
j = j << 33;   // 33 % 32 = 1 左移1位,j变成0,最高位被丢弃
在用gcc编译这段程序的时候编译器会给出一个warning,说左移位数>=类型长度.那么实际上i,j移动的就是1位,也就是33%32后的余数.在gcc下是这个规则,别的编译器是不是都一样现在还不清楚。

同理在右移操作时,也会进行33 % 32 = 1这样的操作。

另外负数右移时,可能会出现-1的情况,这个时候要小心,看是不是右移过多,使符号位填满了整个32位的空间。

负数左移时,可能会出现0,以及溢出数等情况,这也是左移过多造成的。

正数右移,可能会出现0等,也是右移过多造成的。

正数左移,可能会出现溢出数,0等,这都是右移过多造成。

总结左移不要超过(数据类型大小的位数-被操作数的有效位数),

右移不要超过(被操作数的位数)。



你可能感兴趣的:(C语言)