linux有符号和无符号,有符号数和无符号数混用的思考

参考文章:

[1] C语言中无符号数和有符号数之间的运算

[2] 负数在计算机中怎样存储

[3] 二进制减法

1、负数如何在计算机中存储?

原码:10进制转换成2进制是原码,只不过正数的原码是本身符号位为0,负数的原码符号位为1(以下篇幅均以单字节为例:10进制1的原码是0000 0001,10进制-1的原码是1000 0001)。

反码: 正数的反码是本身,负数的反码是负数的原码0变为1,1变为0   (-1的原码是1000 0001   它的反码就是 1111 1110,)。(注意负数求反码时候的符号位不参与变换)。

补码: 正数的补码是本身,负数的反码就是负数的反码加一 (-1的原码是1000 0001   它的反码就是 1111 1110  它的补码就是 1111 1111)。

总结:正数的原码,反码 ,补码三值合一, 负数的原码,反码,补码不同。

为什么要引入反码、补码?

1e44e9e637ca590c8940b94835e41908.png

总结:计算机中正数和负数都是以补码的形式存在的,方便做减法(只不过正数的补码是本身)。

2、无符号数相减为负数(负数符号位忽略,视为无符号数处理)

当表达式中存在有符号数和无符号数时,计算结果会视为无符号数。

unsigned u = 10, u2 = 42;

std:cout << u2 - u << std:endl;

std:cout << u - u2 << std:endl;

输出结果:32    4294967264

u在计算机中的存储:00000000 00000000 00000000 00001010(补码)

u2在计算机中的存储:00000000 00000000 00000000 00101010(补码)

u2 - u:

00000000 00000000 00000000 00101010

- 00000000 00000000 00000000 00001010

00000000 00000000 00000000 00100000 -> 32

u - u2:

00000000 00000000 00000000 00001010

- 00000000 00000000 00000000 00101010

11111111 11111111 11111111 11100000 U -> 4294967264

1db5b14c5451e774b65d9c55d9dfe0e2.png

3、有符号数与无符号数加减运算

当表达式中存在有符号数和无符号数时,计算结果会视为无符号数。

#include "iostream"

using namespace std;

int main()

{

int c = -16;

unsigned int d = 15;

cout << c + d << endl;

return 0;

}

输出结果:4294967295

11111111 11111111 11111111 11110000 (-16补码)

+ 00000000 00000000 00000000 00001111 (15补码)

11111111 11111111 11111111 11111111 (视为无符号数就是4294967295)

注意:这段代码如果写成C形式,输出需要写成如下形式,不然%d指的是有符号数。

printf("%u\n",c + d);

4、有符号数与无符号数比较

#include using namespace std;

int main()

{

int a = -1;

unsigned int b = 16;

if(a > b) {

cout << "a - b = " << a - b << endl;

cout<

输出结果:0005350d940b7fdb1a56b0bfe4d4ff98.png

其实这个很好理解,把 if (a > b) 转换为 if(a - b > 0),现在根据3所述,a - b是大于0的。

11111111 11111111 11111111 11111111 (-1的补码)

- 00000000 00000000 00000000 00010000 (16的补码)

11111111 11111111 11111111 11101111 -> 计算结果视为无符号数,那就是4294967279

5、char和unsigned char混合运算

#include using namespace std;

int main()

{

char a = -1;

unsigned char b = 16;

cout << "a - b = " << a - b << endl;

if(a > b) {

// cout << "a - b = " << a - b << endl;

cout<

输出:2bab8103e7c4b91ecc20c958ee20b45a.png

显然结果与上面不一样了,WHY?

C语言中比int小的整型(包括short 、unsigned short 、 unsigned char和char)在运算中,考虑到运算效率的问题都要转换成int然后进行运算。

如果是unsigned的类型转换成int类型,高位补0.

如果是signed的类型转换成int类型,如果原来最高位是1则补1,如果是0则补0

char a = -1;

a -> 1111 1111 -> 补成int: 11111111 11111111 11111111 11111111

unsigned char b = 16;

b -> 0001 0000 -> 补成int: 00000000 00000000 00000000 00010000

11111111 11111111 11111111 11111111

- 00000000 00000000 00000000 00010000

11111111 11111111 11111111 11101111

对于unsigned short和short进行运算,和char和unsigned char一样,都是要先转换成int,然后再进行运算。

转换时高位补齐的方法也和unsigned char、char一样。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值