关于c语言中左移右移运算符的问题
参照《c与指针》,在c语言中左移时,不论算术左移还是逻辑左移效果都是相同的。而且对于有符号和无符号类型执行相同的操作,即按照二进制位向左左移N位。例如:
1 clude <stdio.h> 2 int main() 3 { 4 int a = 0xafffffff; 5 printf("%d\n",a<<1); 6 int b = 0xff; 7 printf("%d\n",b<<1); 8 }
ubuntu@ubuntu:~/code/2017.8.28$ ./test3 1610612734 510
int型变量a在内存中转换为2进制储存 1010 1111 1111 1111 1111 1111 1111 1111为一个负整数,b在内存中储存为 0000 0000 0000 0000 0000 0000 1111 1111为一个正整数,程序结果如上。a左移后转化为正整数,b转换为正整数 ,都按2进制左移一位(包括符号位)。
而对于右移来讲,针对不同的编译器,可能会进行算术或逻辑移位。在gcc下进行算术移位,即对于正整数右移,算数移位与逻辑移位相同,右移后左端补0,对于负整数右移,算数移位为符号位1不动,右移后左端补1。
1 #include <stdio.h> 2 int main() 3 { 4 int a = 0xafffffff; 5 printf("%d\n",a<<1); 6 int b = 0xff; 7 printf("%d\n",b<<1); 8 }
ubuntu@ubuntu:~/code/2017.8.28$ ./test3 -671088641 127
a作为负数 右移左端补1,b作为正数右移左端补0,验证了以上结论。
在左移右移中,如果数据类型总位数小于int,则先转化为int再进行移位运算。如果左移或右移位数大于数据类型位数,则先进行对数据类型位数取模,再用余数进行移位运算。
1 #include <stdio.h> 2 int main() 3 { 4 char a = 0x11; 5 //for(i = 0;i < 100;i++) 6 //{ 7 // printf("%d\n", a>>i); 8 //} 9 printf("%d\n", a>>(sizeof(int)*8+3)); 10 printf("%d\n", a>>3); 11 printf("%lu\n", sizeof(a>>3)); 12 printf("%ld\n",sizeof(a)) ; 13 }
ubuntu@ubuntu:~/code/2017.8.27$ gcc -o test1 test1.c test1.c: In function ‘main’: test1.c:9:21: warning: right shift count >= width of type [-Wshift-count-overflow] printf("%d\n", a>>(sizeof(int)*8+3)); ^ ubuntu@ubuntu:~/code/2017.8.27$ ./test1 2 2 4 1 ubuntu@ubuntu:~/code/2017.8.27$
针对一个char型数据,当打印sizeof(a>>3)时输出为4,说明此时a>>3这个变量为int型。而上边对于a>>3与a>>(32+3)的输出结果相同,同时系统警告移位大于
数据类型宽度,证明了上文结论。