请问以下在 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%08x b=%#08x \r\n",a,b); a=a<<1; b=b<<1; printf("移位前 a=0x%08x b=%#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 右移两位是 1110 0000 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:}。 |
欢迎光临 独闷闷网 (http://dumenmen.com/) | Powered by Discuz! X3.2 |