(转载)C语言右移运算符的问题(特别当与取反运算符一起时)

(转载)http://hi.baidu.com/fanggai/item/1c44f1f2e3d81dc4a935a266

关键词:C语言,右移运算符,右移运算符+取反运算符,算术右移

环境:VC6.0

由一段C语言面试题引起,对其中的某些运算结果有疑惑,写了段小程序测试了下。
由下面的程序和输出结果得出一些结论:
1.位运算符不改变原变量的值,即无副作用;
2.进行取反运算~时,编译器会将char型转换为int型进行计算(VC6.0,其他编译器未测试),这时要特别注意,一般int型字节数比char型多,转换后高位为0,取反后为1,若后续有右移运算,则会将这些1移入,影响计算结果。

unsigned char a = 0xA5;
unsigned char b = ~a>>4;
printf("b= %d \n", b);//245

a = 0xA5取反后2进制表示为01011010,若按该数值进行右移运算>>4(无论是逻辑右移还是算术右移),则结果应为00000101,对应的十进制数应为5,而输出结果为245,这是为什么呢?
其实应该是这样的:
1)将a转换为int型(4字节),即00::0010100101(32位,::表示20个0);
2)将a取反,则变为11::1101011010(32位,::表示20个1);
3)a开始右移,右移4位,然后截取低8位赋值给b,即11110101,对应的十进制数值为245。

附测试程序如下:
#include <stdio.h>
int main()
{

   unsigned char a = 0x11;//初始值最高位为0
unsigned char b = (~a)<<4;
printf("b= %d \n", b); //224
b = ~a<<4;
printf("b= %d \n", b); //224
b = ~(a<<4);
printf("b= %d\n",b); //239

b = (~a)>>4; //~优先级高于>>
printf("b= %d\n",b);//254
b = ~(a>>4);
printf("b= %d\n",b);//254
b = ~a>>4; //
printf("b= %d\n",b);//254


a = 0xA5; //初始值最高位为1
b = ~a>>4;
printf("b= %d \n", b);//245,

b = (~a)>>4;
printf("b= %d \n", b);//245,


a = 0xA5;
b = a>>4; //没有取反运算
printf("b = %d \n", b); //10,

return 0;                                                                  
}

3.判断VC6.0是逻辑右移还是算术右移

#include <stdio.h>
int main()
{
  int i = 0x80028002;
  int j = i>>31;   // int型变量可以做移位运算
  printf("j= %d \n", j);  // -1,由此判定右移时还是算术右移
}

分析过程:

上述程序输出j = -1,则推断为算术右移。

1)i = 0x80028002的二进制表示1000 0000 0000 0010 1000 0000 0000 0010;

2)由于最高符号位为1,i右移31位,i的二进制表示1111 1111 1111 1111 1111 1111 1111 1111;

3)i的原码表示1000 0000 0000 0000 0000 0000 0000 0001,故i的值为-1。

欢迎讨论。


例子:

#include <stdio.h>

int main(int argc, char** argv)
{
    unsigned char a = 0xa5;
    unsigned char b = (~a) >> 4;

    char c = 0xa5;
    char d = (~c) >> 4;

    printf("%d\n", b);
    printf("%d\n", d);
    printf("\n");
    printf("%d\n", sizeof(~a));

    return 0;
}

程序输出:

b = ~a >> 4的运算顺序肯定是a先取反,但a是字符型,进行取反运算的时候编译器自动转换为int型,于是a变成int型。

然后取反,再进行右移4位操作,就可以得到这个结果了。其实用sizeof(~a)就可以检测出~a之后是int型。

总结:对char、unsigned char取反时,现将其提升为int类型,然后再进行取反。

原文地址:https://www.cnblogs.com/Robotke1/p/3076020.html