C语言位操作符左移和右移实践学习

结论:对C的这两个运算符,左移有无符号对二进制无影响,都是全部左移+补零,一次性移动超过位数内部进行了处理(自动减位数)。

右移有无符号对二进制有影响,有符号的最高位为1(表示负数)则进行右移+补1,其他情况都是右移+补零。

看例子一:有符号数的左移

#include <stdio.h>

int main(){
	int a = 0x80000001;
	int i=0;
	for(;i<64;i++){
		printf("left %d:%08x,%d\n",i,a<<i,a<<i);
	}
}

结果为: 

left 0:80000001,-2147483647
left 1:00000002,2
left 2:00000004,4
left 3:00000008,8
left 4:00000010,16
left 5:00000020,32
left 6:00000040,64
left 7:00000080,128
left 8:00000100,256
left 9:00000200,512
left 10:00000400,1024
left 11:00000800,2048
left 12:00001000,4096
left 13:00002000,8192
left 14:00004000,16384
left 15:00008000,32768
left 16:00010000,65536
left 17:00020000,131072
left 18:00040000,262144
left 19:00080000,524288
left 20:00100000,1048576
left 21:00200000,2097152
left 22:00400000,4194304
left 23:00800000,8388608
left 24:01000000,16777216
left 25:02000000,33554432
left 26:04000000,67108864
left 27:08000000,134217728
left 28:10000000,268435456
left 29:20000000,536870912
left 30:40000000,1073741824
left 31:80000000,-2147483648
left 32:80000001,-2147483647
left 33:00000002,2
left 34:00000004,4
left 35:00000008,8
left 36:00000010,16
left 37:00000020,32
left 38:00000040,64
left 39:00000080,128
left 40:00000100,256
left 41:00000200,512
left 42:00000400,1024
left 43:00000800,2048
left 44:00001000,4096
left 45:00002000,8192
left 46:00004000,16384
left 47:00008000,32768
left 48:00010000,65536
left 49:00020000,131072
left 50:00040000,262144
left 51:00080000,524288
left 52:00100000,1048576
left 53:00200000,2097152
left 54:00400000,4194304
left 55:00800000,8388608
left 56:01000000,16777216
left 57:02000000,33554432
left 58:04000000,67108864
left 59:08000000,134217728
left 60:10000000,268435456
left 61:20000000,536870912
left 62:40000000,1073741824
left 63:80000000,-2147483648

例子二:无符号数的左移

#include <stdio.h>

int main(){
	unsigned int a = 0x80000001;
	int i=0;
	for(;i<64;i++){
		printf("left %d:%08x,%u\n",i,a<<i,a<<i);
	}
}

结果为:

left 0:80000001,2147483649
left 1:00000002,2
left 2:00000004,4
left 3:00000008,8
left 4:00000010,16
left 5:00000020,32
left 6:00000040,64
left 7:00000080,128
left 8:00000100,256
left 9:00000200,512
left 10:00000400,1024
left 11:00000800,2048
left 12:00001000,4096
left 13:00002000,8192
left 14:00004000,16384
left 15:00008000,32768
left 16:00010000,65536
left 17:00020000,131072
left 18:00040000,262144
left 19:00080000,524288
left 20:00100000,1048576
left 21:00200000,2097152
left 22:00400000,4194304
left 23:00800000,8388608
left 24:01000000,16777216
left 25:02000000,33554432
left 26:04000000,67108864
left 27:08000000,134217728
left 28:10000000,268435456
left 29:20000000,536870912
left 30:40000000,1073741824
left 31:80000000,2147483648
left 32:80000001,2147483649
left 33:00000002,2
left 34:00000004,4
left 35:00000008,8
left 36:00000010,16
left 37:00000020,32
left 38:00000040,64
left 39:00000080,128
left 40:00000100,256
left 41:00000200,512
left 42:00000400,1024
left 43:00000800,2048
left 44:00001000,4096
left 45:00002000,8192
left 46:00004000,16384
left 47:00008000,32768
left 48:00010000,65536
left 49:00020000,131072
left 50:00040000,262144
left 51:00080000,524288
left 52:00100000,1048576
left 53:00200000,2097152
left 54:00400000,4194304
left 55:00800000,8388608
left 56:01000000,16777216
left 57:02000000,33554432
left 58:04000000,67108864
left 59:08000000,134217728
left 60:10000000,268435456
left 61:20000000,536870912
left 62:40000000,1073741824
left 63:80000000,2147483648

 

例子三:有符号数的右移:

#include <stdio.h>

int main(){
	int a = 0x80000001;
	int i=0;
	for(;i<64;i++){
		printf("left %d:%08x,%d\n",i,a>>i,a>>i);
	}
}

结果为:

left 0:80000001,-2147483647
left 1:c0000000,-1073741824
left 2:e0000000,-536870912
left 3:f0000000,-268435456
left 4:f8000000,-134217728
left 5:fc000000,-67108864
left 6:fe000000,-33554432
left 7:ff000000,-16777216
left 8:ff800000,-8388608
left 9:ffc00000,-4194304
left 10:ffe00000,-2097152
left 11:fff00000,-1048576
left 12:fff80000,-524288
left 13:fffc0000,-262144
left 14:fffe0000,-131072
left 15:ffff0000,-65536
left 16:ffff8000,-32768
left 17:ffffc000,-16384
left 18:ffffe000,-8192
left 19:fffff000,-4096
left 20:fffff800,-2048
left 21:fffffc00,-1024
left 22:fffffe00,-512
left 23:ffffff00,-256
left 24:ffffff80,-128
left 25:ffffffc0,-64
left 26:ffffffe0,-32
left 27:fffffff0,-16
left 28:fffffff8,-8
left 29:fffffffc,-4
left 30:fffffffe,-2
left 31:ffffffff,-1
left 32:80000001,-2147483647
left 33:c0000000,-1073741824
left 34:e0000000,-536870912
left 35:f0000000,-268435456
left 36:f8000000,-134217728
left 37:fc000000,-67108864
left 38:fe000000,-33554432
left 39:ff000000,-16777216
left 40:ff800000,-8388608
left 41:ffc00000,-4194304
left 42:ffe00000,-2097152
left 43:fff00000,-1048576
left 44:fff80000,-524288
left 45:fffc0000,-262144
left 46:fffe0000,-131072
left 47:ffff0000,-65536
left 48:ffff8000,-32768
left 49:ffffc000,-16384
left 50:ffffe000,-8192
left 51:fffff000,-4096
left 52:fffff800,-2048
left 53:fffffc00,-1024
left 54:fffffe00,-512
left 55:ffffff00,-256
left 56:ffffff80,-128
left 57:ffffffc0,-64
left 58:ffffffe0,-32
left 59:fffffff0,-16
left 60:fffffff8,-8
left 61:fffffffc,-4
left 62:fffffffe,-2
left 63:ffffffff,-1

第二种:

#include <stdio.h>

int main(){
	int a = 0x10000001;
	int i=0;
	for(;i<64;i++){
		printf("left %d:%08x,%d\n",i,a>>i,a>>i);
	}
}

 结果为:
 

left 0:10000001,268435457
left 1:08000000,134217728
left 2:04000000,67108864
left 3:02000000,33554432
left 4:01000000,16777216
left 5:00800000,8388608
left 6:00400000,4194304
left 7:00200000,2097152
left 8:00100000,1048576
left 9:00080000,524288
left 10:00040000,262144
left 11:00020000,131072
left 12:00010000,65536
left 13:00008000,32768
left 14:00004000,16384
left 15:00002000,8192
left 16:00001000,4096
left 17:00000800,2048
left 18:00000400,1024
left 19:00000200,512
left 20:00000100,256
left 21:00000080,128
left 22:00000040,64
left 23:00000020,32
left 24:00000010,16
left 25:00000008,8
left 26:00000004,4
left 27:00000002,2
left 28:00000001,1
left 29:00000000,0
left 30:00000000,0
left 31:00000000,0
left 32:10000001,268435457
left 33:08000000,134217728
left 34:04000000,67108864
left 35:02000000,33554432
left 36:01000000,16777216
left 37:00800000,8388608
left 38:00400000,4194304
left 39:00200000,2097152
left 40:00100000,1048576
left 41:00080000,524288
left 42:00040000,262144
left 43:00020000,131072
left 44:00010000,65536
left 45:00008000,32768
left 46:00004000,16384
left 47:00002000,8192
left 48:00001000,4096
left 49:00000800,2048
left 50:00000400,1024
left 51:00000200,512
left 52:00000100,256
left 53:00000080,128
left 54:00000040,64
left 55:00000020,32
left 56:00000010,16
left 57:00000008,8
left 58:00000004,4
left 59:00000002,2
left 60:00000001,1
left 61:00000000,0
left 62:00000000,0
left 63:00000000,0

例子四:无符号数的右移:
 

#include <stdio.h>

int main(){
	unsigned int a = 0x10000001;
	int i=0;
	for(;i<64;i++){
		printf("left %d:%08x,%u\n",i,a>>i,a>>i);
	}
}

结果为:

left 0:80000001,2147483649
left 1:40000000,1073741824
left 2:20000000,536870912
left 3:10000000,268435456
left 4:08000000,134217728
left 5:04000000,67108864
left 6:02000000,33554432
left 7:01000000,16777216
left 8:00800000,8388608
left 9:00400000,4194304
left 10:00200000,2097152
left 11:00100000,1048576
left 12:00080000,524288
left 13:00040000,262144
left 14:00020000,131072
left 15:00010000,65536
left 16:00008000,32768
left 17:00004000,16384
left 18:00002000,8192
left 19:00001000,4096
left 20:00000800,2048
left 21:00000400,1024
left 22:00000200,512
left 23:00000100,256
left 24:00000080,128
left 25:00000040,64
left 26:00000020,32
left 27:00000010,16
left 28:00000008,8
left 29:00000004,4
left 30:00000002,2
left 31:00000001,1
left 32:80000001,2147483649
left 33:40000000,1073741824
left 34:20000000,536870912
left 35:10000000,268435456
left 36:08000000,134217728
left 37:04000000,67108864
left 38:02000000,33554432
left 39:01000000,16777216
left 40:00800000,8388608
left 41:00400000,4194304
left 42:00200000,2097152
left 43:00100000,1048576
left 44:00080000,524288
left 45:00040000,262144
left 46:00020000,131072
left 47:00010000,65536
left 48:00008000,32768
left 49:00004000,16384
left 50:00002000,8192
left 51:00001000,4096
left 52:00000800,2048
left 53:00000400,1024
left 54:00000200,512
left 55:00000100,256
left 56:00000080,128
left 57:00000040,64
left 58:00000020,32
left 59:00000010,16
left 60:00000008,8
left 61:00000004,4
left 62:00000002,2
left 63:00000001,1

注意

以上的例子都有个bug,就是我会格式化输出,a<<i的数,这样就会导致就算a为char类型,对结果也没有影响,因为输出的实际上是a<<i的返回值,而不是a,中间加一步赋值到另外一个char的结果就不一样。

拓展

#include <stdio.h>

int main(){
	int a = 0x80000001;
	int b = 0;
	int i=4;
		b = a<<32;
		printf("left %d:%08x,%d\n",i,b,b);
		b = a<<31;
		printf("left %d:%08x,%d\n",i,b,b);
		b = b<<1;
		printf("left %d:%08x,%d\n",i,b,b);

}

结果为:

left 4:80000001,-2147483647
left 4:80000000,-2147483648
left 4:00000000,0

这个一次移动32位和先移动31位再移动1位的结果是不同的,具体细节牵扯到指令级别的,但是8位和16位并不会有不同结果。保留该疑惑!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值