按位NOT(〜)的奇怪行为

时间:2011-08-28 05:44:13

标签: c++ c types bit-manipulation

如何解释以下行为?

#include<iostream>

using namespace std;

int main(){

       unsigned char a = 8;

       cerr << "a: " << (int)a << '\n';

       unsigned char b = (~a) >> 6;

       cerr << "b: " << (int)b << '\n';

       unsigned char c = (~a);
       c = c >> 6;

       cerr << "c: " << (int)c << '\n';

       return 0;
}

输出:

a: 8
b: 255
c: 3

经过进一步测试后,似乎(~a)变为int而不是unsigned char。这就是1被移入的原因。

发生了什么事?

编辑:我的编译器只是标准的gcc 4.1.2

4 个答案:

答案 0 :(得分:22)

C中的所有算术运算符和按位运算符如果原始是较短的整数类型,则始终将其参数扩展至至少int。这就是语言的定义方式。语言规范称之为“整体推广”。

(其根本原因是为了更容易在架构上实现C,其中硬件不支持比完整机器字更短的数量的有效操作。当然,这也部分仅仅因为它一直以这种方式工作如果不破坏依赖于此行为的大量现有代码,则无法更改。

答案 1 :(得分:2)

~a = 0xFFFFFFF7,因此b = (~a) >> 6会产生b = 0xFF;如果是c,我们c = (~a);导致c = 0xF7,因此c>>6将为3. Henning Makholm在上面很好地解释了整数提升。这个article也很有用。

答案 2 :(得分:1)

因为这行...

unsigned char b = (~a) >> 6;

编译器生成的临时变量为char (〜a),在向右移后, LSB 字节b为 0xff

但这行...

   unsigned char c = (~a);
   c = c >> 6;

不需要编译器来构建临时var,并且(〜a)的值为 0x7f ,而向右移后的c为 0x03 < / p>

答案 3 :(得分:0)

a = 8

~a = -9 (int)

~a >> 6 = -1 (int)

(unsigned char)-1 = 255