浅谈C语言的逻辑位移与算术位移
请问以下在 VISUAL C++编译环境中结果是多少#include <stdio.h>
void main()
{
printf("%d\r\n" ,(1<<15)>>15);
printf("%d\r\n" ,(1<<31)>>31);
}答案是
你算对了吗??? C语言的位移运算,按位移的方向,可分为左移与右移,按位移的性质可分为逻辑位移与算术位移。 逻辑位移内容,是位与位之间的逻辑关系,其准则为:左移即高位溢出摒弃,低位腾空补零。右移低位溢出摒弃,高位腾空是补零。 算术位移的内容是运算,如右移一位即除以2。 当为左移运算时,无论左移的操作对象是有符号的整形数还是无符号的整形数,都是逻辑左移运算。即高位溢出摒弃,低位腾空补零。如以下代码
#include <stdio.h>void main(){int a=0X80000000; //最高位为1 负数unsigned int b=0x00000001; printf("移位前a=0x%08xb=%#08x\r\n",a,b);a=a<<1;b=b<<1;printf("移位前a=0x%08xb=%#08x\r\n",a,b); }
其运行结果为
大家注意到了没有,负数a左移移位之后结果为0,符号位溢出摒弃,这里不是算术位移,而是逻辑位移。 当为右移运算时,则要根据数据的类型,当操作对象是无符号整形数时,则是逻辑右移,即所谓的高位腾空补零,低位溢出摒弃。 而操作对象是有符号整形数,这时大家注意了,大多数编译器是做算术位移处理的。低位溢出摒弃,高位腾空是补零或是1,则根据为数据的符号,如果是正数,补零,如果是负数,则是补一。我们这里重点讨论一下有符号整形数的右移运算#include <stdio.h>
void main()
{
int a=0x80000000;//最高位为1,即为负数
int b=0x40000000 ;//最高位为0,即为正数
printf("移位前....................\r\n");
printf("a=0x%08x十进制表示%d\r\n",a,a);
printf("b=0x%08x十进制表示%d\r\n",b,b);
a=a>>1 ;
b=b>>1 ;
printf("移位后....................\r\n");
printf("a=0x%08x十进制表示%d\r\n",a,a);
printf("b=0x%08x十进制表示%d\r\n",b,b);
}
其运算结果为
负数a右移一位,做算术位移,高位补1。移位之后满足算术逻辑 a=-2147483648/2=-1073741824
正数b右移一位 做算术位移,高位补0 。b=1073741824/2=536870912 不知道大家看到这里,本文章一开始的代码大家能解释了吗.编译器整形数默认是int printf("%d\r\n" ,(1<<15)>>15);结果为0相信很好解释,左移15位,最高位是0,正数,右移15位,高位补0,结果还是1 printf("%d\r\n" ,(1<<31)>>31);先是做逻辑运算,左移31位,此时做高位是1,为负数,此时右移,做算术逻辑,高位补一右移一位是 1100 0000 0000 0000 0000 0000 0000 右移两位是 11100000 0000 0000 0000 0000 0000 ......................... 右移31位是 1111 1111 1111 1111 1111 1111 1111 大家知道,因为负数的原码最高位符号位不能直接参与运算,为避免额外的硬件开销,负数在计算机存储是以补码的形式存在的。他的原码是:补码保留符号位不变,其他数取反加1,即 1000 0000 0000 0000 0000 0000 0000 0001即-1的源码,验证了我们的结果。个人见解,多多指教{:soso_e113:}。
3.png (10.49 KB, 下载次数: 0) 下载附件保存到相册
昨天 21:23 上传 http://www.dumenmen.com/static/image/common/rleft.gif http://www.dumenmen.com/static/image/common/rright.gif
感谢你的分享和付出。 谢谢分享:lol
页:
[1]