是对C/C++下面的结果感到困惑?
printf("%d\n", ((unsigned char)~0 >> 1)); //结果为127
printf("%d\n", -((unsigned char)~0 >> 1)); //结果为-127
printf("%d\n", ((signed char)~0 >> 1)); //结果为-1
printf("%d\n", -((signed char)~0 >> 1)); //结果为1
我们来一步一步分析一下!
是对C/C++下面的结果感到困惑?
printf("%d\n", ((unsigned char)~0 >> 1)); //结果为127
printf("%d\n", -((unsigned char)~0 >> 1)); //结果为-127
printf("%d\n", ((signed char)~0 >> 1)); //结果为-1
printf("%d\n", -((signed char)~0 >> 1)); //结果为1
我们来一步一步分析一下!
一、运算符优化级
~按位取反运算符 优先级高于 >>右移位运算符
(unsigned char)~0 >> 1 //0取反为二进制11111111,无符号数右移1位为01111111,结果为127
(signed char)~0 >> 1 //0取反为二进制11111111,有符号数右移1位为11111111,结果为-1
~按位取反运算符 优先级高于 >>右移位运算符
(unsigned char)~0 >> 1 //0取反为二进制11111111,无符号数右移1位为01111111,结果为127
(signed char)~0 >> 1 //0取反为二进制11111111,有符号数右移1位为11111111,结果为-1
二、有符号数和无符号数的右移
为什么无符号数11111111右移1位为01111111,而有符号数11111111右移1位为11111111呢?
移位时,移出的位数全部丢弃,移出的空位补入的数与左移还是右移有关。如果是左移,则规定补入的数全部是0;如果是右移,还与被移位的数据是否带符号有关。若是不带符号数,则补入的数全部为0;若是带符号数,则补入的数全部等于原数的最左端位上的原数(即原符号位)
为什么无符号数11111111右移1位为01111111,而有符号数11111111右移1位为11111111呢?
移位时,移出的位数全部丢弃,移出的空位补入的数与左移还是右移有关。如果是左移,则规定补入的数全部是0;如果是右移,还与被移位的数据是否带符号有关。若是不带符号数,则补入的数全部为0;若是带符号数,则补入的数全部等于原数的最左端位上的原数(即原符号位)
三、原码与补码
为什么无符号数01111111为127,有符号数11111111为-1?
在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理。此外,补码与原码相互转换,其运算过程是相同的。
补码的表示方法是:正数的补码就是其本身;负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1,即在反码的基础上+1。
所以对于负数, 补码表示方式也是人脑无法直观看出其数值的. 通常也需要转换成原码在计算其数值.
为什么无符号数01111111为127,有符号数11111111为-1?
在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理。此外,补码与原码相互转换,其运算过程是相同的。
补码的表示方法是:正数的补码就是其本身;负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1,即在反码的基础上+1。
所以对于负数, 补码表示方式也是人脑无法直观看出其数值的. 通常也需要转换成原码在计算其数值.