在进入正题前,我们必须知道 :
1、各种数据格式(整型int,字符型char等)占有几个存储单元(不同的编译器有所不同)
在TC2.0和keil中:(也是ANSI的标准)
char占有1个字节(即8位二进制数)。unsigned
char类型的变量,最大值为0xff(十六进制),255(十进制)
int占有2个字节(即16位二进制数)。unsigned
int类型的变量,最大值为0xffff(十六进制),65535(十进制)
long int占有4个字节
folat占有4个字节,long float 和double都占有8个字节,long
double 占16个字节
在VC++中:
char占有1个字节,int和float占有4个字节,double占有8个字节
2、逻辑左移/右移和算术左移/右移的区别(这两种位运算,仅适用于整型和字符型。对实数型格式的数据不适用)
逻辑左移:丢弃最低位,0补最高位。(假设仅左移1位)二进制数:1111
1111逻辑左移1位,得:0111 1111
逻辑右移:丢弃最高位,0补最低位。(假设仅右移1位)二进制数:1111
1111逻辑左移1位,得:1111 1110
算术左移:以保持符号位不变为基础,进行逻辑左移。(假设仅左移1位)二进制数:1000
1111得:1100 0111
算术右移:以保持符号位不变为基础,进行逻辑右移。(假设仅右移1位)二进制数:1000
1111得:1001 1110
好了,进入正题:(分无符型和有符型进行讨论)
以下结果,是通过VC++6.0调试的(char占1字节,int占4字节)
需要注意的一点是:计算里的运算都是通过二进制补码进行的,所以在对两个操作数进行运算时,要先将它们转化成补码形式。
1、无符型情况 unsigned char 和unsigned
int
(以unsigned char型为例,unsigned
int型情况相同)
>>右移
unsigned char i=0x99;//二进制数补码形式为:1001
1001
i=i>>1;
printf("\ni=0x%x\n",i);//%x是指,运行的结果以十六进制的形式显示
程序运行结果:
i=0x4c;即0100 1100
<
i=0x99;
i=<<1;
程序运行结果:
i=0x32;即0011 0010
2、有符型 char和int
左移<<
char
i= - 9; //i的二进制原码:1000 1001补码:1111 0111
char
j=9; //j的二进制原码:0000 1001 补码:和原码一样
char
x=0x49; //x的二进制原码:0100 1001 补码:和原码一样
char
y=-0x49; //y的二进制原码:1100 1001 补码:1011 0111
i=i<<1; //经逻辑左移后,i的补码:1110
1110(是个负数,需再求其补),得原码:1001 0010 即-18(十进制)
j=j<<1; //经逻辑左移后,j的补码:0001
0011(是个正数,原码和补码一样)即18(十进制)
x=x<<1;
//经逻辑左移后,x的补码:1001 0010(是个负数,需再求其补),得原码:1110
1110即-110(十进制)
y=y<<1; //经逻辑左移后,y的不码:0110
1110(是个正数,原码和补码一样)即110(十进制)
printf("i=%d\nj=%d\nx=%d\n",i,j,x);
程序运行结果:
i= -
18;
j=18;
x= -
110;
y=110;
——右移>>和左移<
结论结论结论结论结论结论 结论
在C语言中,VC++6.0环境下:
对一个数进行位移操作,就是对它的补码进行逻辑位移操作
如果这个数是无符型,则逻辑操作的结果就是它的最终位运算结果;
如果这个数是有符型,则还需对个逻辑操作的结果进行一次取补,取补后的结果方为最终运算结果。
补充说明:
1、如果位移动的数目大于或等于它本身存储位数,即对一个char型变量进行大于或等于8次的左移或右移操作,若原变量是正数,则结果必为0;若原变量是负数,则其结果必为-1。如:char
i=9;char
j=-10;i=i<<10;j=j>>10;则i为0,j为-1。
2、对于char
x;如果令x=0x80;会提示错误。因为x的范围是-0x7f到0x7f.
郑重说明:
下面的两个参考资料中描述的结论均是在GCC环境下获得,与本文通过VC++6.0调试的结果大不相同。望读者根据自己的编辑器,选择性使用。
参考资料:
http://www.docin.com/p-55526990.html
http://blog.chinaunix.net/u/19186/showart_167761.html