开发者

Strange behavior of bitwise NOT (~)

开发者 https://www.devze.com 2023-03-31 01:36 出处:网络
How do I explain the following behavior? #include<iostream> using namespace std; int main(){ unsigned char a = 8;

How do I explain the following behavior?

#include<iostream>

using namespace std;

int main(){

       unsigned char a = 8;

       cerr <&l开发者_如何学Pythont; "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;
}

Output:

a: 8
b: 255
c: 3

After further testing it seems that (~a) becomes an int rather than unsigned char. This is why the 1's get shifted in.

What's going on?

EDIT: My compiler is just standard gcc 4.1.2


All arithmetic and bitwise operators in C always widen their arguments to at least int if they were originally shorter integral types. That's just how the language is defined. The language specification calls this the "integral promotion".

(The underlying reason for this is to make it easier to implement C on architectures where the hardware does not support efficient operations on shorter quantities than a full machine word. Of course, it's also partly just because it has always worked that way and cannot be changed without breaking a lot of existing code that depends on this behavior).


~a = 0xFFFFFFF7, so b = (~a) >> 6 results in b = 0xFF; In case of c we have c = (~a); resulting in c = 0xF7, therefore c>>6 will be 3. Henning Makholm explains integer promotion nicely above. This article is also useful.


a = 8

~a = -9 (int)

~a >> 6 = -1 (int)

(unsigned char)-1 = 255


because this line...

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

compiler build the temporary var is signed char (~a) and after the shift right and LSB byte b is 0xff

but this lines...

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

compiler not needed to build the temporary var and (~a) value is 0x7f, and after the shift right c is 0x03

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号