首先看以下一段代码:
1 #include <cstdio>
2
3 int main()
4 {
5 unsigned char t = 0xa5;
6 unsigned char i = (~t)>>4;
7 printf("%x\n", i);
8 return 0;
9 }
建议最好仔细先想一下再往下看
对于char、bool、unsigned char等低于int字节数的类型,进行运算的时候首先进行提升,因此在进行~t运算之前,先要将其放入32位寄存器,由于是unsigned char,因此前面补位全补0,因此0xa5-->0x000000a5,然后取反为0xffffff5a,然后再向右移四位为0xfffffff5,然后再转化为unsigned char型的0xf5赋值给i,因此最后输出结果为0xf5
再看下面这段代码:
1 #include <cstdio>
2
3 int main()
4 {
5 char t = 0xa5;
6 char i = (~t)>>4;
7 printf("%x\n", i);
8 return 0;
9 }
思想和上面的完全相同,还是先提升为int然后再进行运算,但是注意这里是char型,因此提升的时候应该是根据最高位进行提升,最高位为1则前面全补全为1,否则全补全为0。因此再进行~t操作前应该先补全为0xffffffa5,然后进行取反操作为0x0000005a,然后再右移四位为0x00000005,再转化成char型的0x05赋值给i,因此最后结果为0x5
再看最后一个例子:
1 #include <cstdio>
2
3 int main()
4 {
5 char a = 0x80;
6 char b = 0x2;
7 unsigned char c = 0x80;
8 unsigned char d = 0x2;
9 printf("%x\n", a / b);
10 printf("%x\n", c / d);
11 return 0;
12 }
13
主要是巩固前面说过的情况,非常类似,进行运算之前,a、b、c、d都要先补齐为:
a--->0xffffff80
b--->0x00000002
c--->0x00000080
d--->0x00000002
然后再进行运算,因此结果为:
0xffffffc0
0x40
最后再总结一下:unsigned char、char、bool等低于int型的类型,进行运算的时候都要先提升再运算,提升时根据signed和unsigned,在前面补位为0或者1,若是unsigned,则直接前面全补0;若为signed,则根据最高位为0还是1,若为0则全部补位为0,若为1则全部补位为1。
编写安全代码——小心有符号数的右移操作
阅读(3867) | 评论(0) | 转发(0) |