位运算的小问题

         之前学习c语言的时候课程中并没有介绍过位操作,关于位操作也是之后零零散散地遇到。最近又遇到了一个问题,索性就总结一下吧。

         问题大概是这样的:

unsigned char x = 0xf4;
printf( "%x",~x );

          输出是什么??

         之前以为是 b。因为16进制 f4 = 1111,0100,取反之后是 0000,1011,即是b。但是结果却是ffffff0b。

         其实这还涉及到一个“Integer Promotion”的问题:在一个表达式中,凡是可以使用int或unsigned int类型做右值的地方也都可以使用有符号或无符号的char型、short型和Bit-field。如果原始类型的取值范围都能用int型表示,则其值被提升为int型,如果表示不了就提升为unsigned int型。

         在这里,可以理解实际上有一个整型y(16进制)

y  = ~x

         进行计算时,首先需要把字符型的x转成整型,此时x实际为:0x000000f4。然后再进行取反运算,达到:0xffffff0b

        

         还有一个比较容易出错的问题就是有符号数的移位了,比如:

int i = 0xcffffff3;
printf("%x\n",0xcffffff3 >> 2);
printf("%x\n",i >> 2);

得到的竟是两个不一样的结果:33fffffcf3fffffc

         仔细分析其实不难理解。第一句的输出是正常的整数移位,按正常的步骤就能得到结果。而第二句是整型的移位,是有符号位的。即i的存储是:

1100,1111,...,0011

可以看出最高位,即符号位是1,说明是负数。所以编译器在进行移位操作的时候是补1而不是补0,所以向右移两位后,是:

                                                                           1111,0011,1111,...,1100

 

         此外,还有一个需要注意的问题就是:移动的位数必须小于左操作数的总位数。

         例如:

int i = 0xcffffff3;
printf("%x\n",i >> 33);

此时,虽然也能得到结果:e7fffff9,但是却会报一个warning



说到位运算,其实有很多性质,我们可以巧妙地利用,从而带来一定程度上的优化。最典型的就是不借助额外的存储空间来进行两个整数的交换:

a = a ^ b;
b = b ^ a;
a = a ^ b;


还有就是利用掩码来对特定的位进行提取、置零、置一的操作,这些可以对一些位图进行简单的处理操作。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值