Chinaunix首页 | 论坛 | 博客
  • 博客访问: 515399
  • 博文数量: 77
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 689
  • 用 户 组: 普通用户
  • 注册时间: 2013-08-12 08:40
文章分类

全部博文(77)

文章存档

2018年(1)

2016年(3)

2015年(24)

2014年(49)

我的朋友

分类: C/C++

2014-11-06 16:13:43


首先看以下一段代码:

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) |
给主人留下些什么吧!~~