昨天记录了一下c和java中的位运算符c和java中的位运算对比—补码运算,发现其实位运算都是针对补码进行运算,但是没有记录移位运算,这里记录一下。
java:主要的结论如下:
1. <<,左移。低位补0。
2. >>,右移。被操作数如果为正数,高位补0;如果为负数,高位补1。
3. java中没有无符号左移,只有无符号右移>>>。不管被操作数为正数还是负数,最高位均补0(视操作位为无符号正数)。
4. 在移位时,byte/short/char类型数,在移位前会被转化为int型(按数值进行转换)。
5. 对于byte/short/char/int型数据,实际移动的次数是 n % 32位。
6. 对于long型,实际移位的次数是 n % 64。
7. 浮点数不能进行移位操作。
验证代码如下:
public class URShift {
public static void main(String[] args) {
//进行移位运算时,位内存中补码的形式
// 0000 0000 0000 0000 0000 0000 1111 1111
//<< 1
// 0000 0000 0000 0000 0000 0001 1111 1110
//左移了1位,低位补0
System.out.println("<<1:" + Integer.toBinaryString(0xff << 1));//1 1111 1110
// 1111 1111 1111 1111 1111 1111 0000 0001
// <<1
// 1111 1111 1111 1111 1111 1110 0000 0010
//左移了1位,低位补0
System.out.println("<<1:" + Integer.toBinaryString(-0xff << 1));//11111111111111111111111000000010
//编译错误,java中没有无符号左移
//System.out.println("l<<<" + (l <<< 64));
//转化为10进制,结果为-510 != -256 * 2,这里也证明了原来老师教的左移1位相当于乘以2是扯蛋的,不负责任的,至少对于负数是存在错误的
System.out.println(-0xff << 1);//-510
// 0000 0000 0000 0000 0000 0000 1111 1111
//>> 1
// 0000 0000 0000 0000 0000 0000 0111 1111
//右移了1位,高位补0
System.out.println(">>1:" + Integer.toBinaryString(0xff >> 1));//111 1111
// 0000 0000 0000 0000 0000 0000 1111 1111
//>>> 1
// 0000 0000 0000 0000 0000 0000 0111 1111
// 右移了1位,高位补0
System.out.println(">>>1:" + Integer.toBinaryString(0xff >>> 1));//111 1111
// 1111 1111 1111 1111 1111 1111 0000 0001
// >> 1
// 1111 1111 1111 1111 1111 1111 10000000
//右移了1位,高位补1
System.out.println(">>1:" + Integer.toBinaryString(-0xff >> 1));//11111111111111111111111110000000
// 1111 1111 1111 1111 1111 1111 0000 0001
// >> 1
// 0111 1111 1111 1111 1111 1111 1000 0000
//右移了1位,高位补0
System.out.println(">>>1:" + Integer.toBinaryString(-0xff >>> 1));//1111111111111111111111110000000
// 0000 0000 0000 0000 0000 0000 1111 1111
//<< 31
// 1000 0000 0000 0000 0000 0000 0000 0000
System.out.println("<<31:" + Integer.toBinaryString(0xff << 31));//10000000000000000000000000000000
// 1111 1111 1111 1111 1111 1111 0000 0001
// <<31
// 1111 1111 1111 1111 1111 1111 0000 0001
System.out.println("<<31:" + Integer.toBinaryString(-0xff << 31));//11111111111111111111111100000001
//1111 1111 1111 1111 1111 1111 0000 0001
//>>31
//1111 1111 1111 1111 1111 1111 1111 1111
System.out.println(">>31:" + Integer.toBinaryString(-0xff >> 31));//11111111111111111111111111111111
//对于byte/short/char/int型数据,实际移动的次数是 n % 32位
// 1111 1111 1111 1111 1111 1111 0000 0001
//<< 32 相当于移位32 % 32 = 0位
// 1111 1111 1111 1111 1111 1111 0000 0001
System.out.println("<<32:" + Integer.toBinaryString(-0xff << 32));//11111111111111111111111100000001
// 1111 1111 1111 1111 1111 1111 0000 0001
//>>32 相当于移位32 % 32 = 0位
// 1111 1111 1111 1111 1111 1111 0000 0001
System.out.println(">>32:" + Integer.toBinaryString(-0xff >> 32));//11111111111111111111111100000001
char ch = 0xff;
char che = (char)(-0xff);
//在移位时,byte/short/char类型数,在移位前会被转化为int型
// 0000 0000 0000 0000 0000 0000 1111 1111
//<< 31
// 1000 0000 0000 0000 1111 1111 0000 0000
System.out.println("ch<<8:" + Integer.toBinaryString(ch << 8));//1111111100000000
// 1111 1111 1111 1111 1111 1111 0000 0001
//<< 31
// 0000 0000 1111 1111 0000 0001 0000 0000
System.out.println("che << 8:" + Integer.toBinaryString(che << 8));//111111110000000100000000
//对于long型,实际移位的次数是 n % 64
//0x7fffffffffffffff
//<<64 相当于移位64 % 64 = 0 位
// 7fffffffffffffff
long l = Long.MAX_VALUE;
System.out.println("l<<64:" + Long.toHexString(l << 64));
//编译错误,浮点数不能进行移位操作
//System.out.println("0.1 >> 1" + (0.1 >>1));
short s = -1;
System.out.println(Integer.toBinaryString(s));
s >>>= 10;
//运算时先转换为int型,值为1111 1111 1111 1111 1111 1111 1111 1111
//由于赋值时转换为short型数据,前半部分被截断,赋值为1111 1111 1111 1111,真值也为-1
System.out.println(Integer.toBinaryString(s));
}
}
c语言结论如下:
1. <<,左移。低位补0。
2. >>,右移。被操作数如果为正数,高位补0;如果为负数,高位补1。
3. c语言中没有无符号移位
4. 在移位时,byte/short/char类型数,在移位前后都不会被转化为int型。
5. 如果移位溢出,不会处理,会得到随机值。
6. 浮点数不能进行移位操作。
验证代码如下:
#include <stdio.h>
int main(){
//进行移位运算时,位内存中补码的形式
//左移1位,低位补0
printf("%x\n", 0xff << 1);//1fe
printf("%x\n", -0xff << 1);//fffffe02
//右移1位,高位补0
printf("%x\n", 0xff >> 1);//7f
//右移1位,高位补1
printf("%x\n", -0xff >> 1);//ffffff80
printf("%x\n", (-0xff << 31));//80000000
printf("%x\n", (-0xff >> 31));//ffffffff
printf("%x\n", (0xff << 32));//得到的是1个随机值
printf("%x\n", (0xff >> 32));//得到的是1个随机值
long l = 0xff;
printf("%d\n", sizeof(long));
printf("%lx\n", l << 32);//ff 00 00 00 00
short ch = -1;
char che = (char)(-0xff);
printf("%x\n", ch << 1);//ff ff ff fe,可以看出运算结果并没有转换为int型
//编译错误,c语言中没有无符号移位
//printf("%x\n", 0xff <<< 1);
//printf("%d\n", 0xff >>> 1);
//编译错误,小数不能进行移位运算
//printf("%x\n", 0.1 << 1);
return 0;
}