看到一道笔试题,跟自己想的有点出入,就跑了下,看了看原因。
代码我稍微改了下:
#include <stdio.h>
int main(int argc, char* argv[])
{
unsigned char a = 0xA5;
unsigned char b = ~a;
unsigned char c = b >> 4;
unsigned char d = ~a >> 4;
printf("c = %d d = %d \n", c, d);
return 0;
}
输出结果:
c = 5 d = 245
Press any key to continue
VC6.0 debug下的汇编代码
5: unsigned char a = 0xA5;
0040D738 mov byte ptr [ebp-4],0A5h
6: unsigned char b = ~a;
0040D73C mov eax,dword ptr [ebp-4]
0040D73F and eax,0FFh
0040D744 not eax
0040D746 mov byte ptr [ebp-8],al
7: unsigned char c = b >> 4;
0040D749 mov ecx,dword ptr [ebp-8]
0040D74C and ecx,0FFh
0040D752 sar ecx,4
0040D755 mov byte ptr [ebp-0Ch],cl
8: unsigned char d = ~a >> 4;
0040D758 mov edx,dword ptr [ebp-4]
0040D75B and edx,0FFh
0040D761 not edx
0040D763 sar edx,4
0040D766 mov byte ptr [ebp-10h],dl
在执行 unsigned char d = ~a >> 4; 时先将 a 转换成4字节,运算完毕后在转换为单字节类型。
因为 >> (对应sar指令)是32位数算术右移指令,故先将a扩充至32位。
sar执行的操作:右移时,符号位(最高位)移到次高位的同时其值保持不变。也就是说,右移时空出的最高位用它自身原有的值填入,如果原来是0,则填入0;原来是1,填入1。