原码、反码、补码以及大小端和整形提升


前言

1、计算机在底层存储数据时只能识别二进制,计算机在存储数据时,一律存储的是“二进制的补码”形式

计算机采用补码形式存储数据的原因是:CPU 只有加法器
1)因为使用补码可以将符号位和其他位统一处理,同时,减法也可以按加法来处理,即如果是补码表示的数,不管是加减法都直接用加法运算即可实现。

2)两个用补码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃。

这样的运算有两个好处:

1)使符号位能与有效值部分一起参加运算,从而简化运算规则。从而可以简化运算器的结构,提高运算速度;(减法运算可以用加法运算表示出来。)

2)加法运算比减法运算更易于实现。使减法运算转换为加法运算,进一步简化计算机中运算器的线路设计。


一、原码、补码、反码

(1)计算机中的整数有三种表示方法,即原码、反码和补码,三种表示方法均有 符号位 和 数值位 两部分符号位都是用0表示“正”,用1表示“负”,而数值位负整数的三种表示方法各不相同。

原码
直接将二进制按照正负数的形式转换成二进制就可以。

反码
原码符号位不变,其他位按位取反就可以得到反码。

补码
反码+1就可以得到补码。

正数的原、反、补码都相同
负数的原码、反码、补码是需要计算的
对于整形来说,数据存放内存中其实是存放的补码

int main()
{
	int a = 10;//整型值
	//原码:00000000000000000000000000001010
	//反码:00000000000000000000000000001010
	//补码:00000000000000000000000000001010

	int b = -10;//整型值
	//原码:10000000000000000000000000001010
	//反码:11111111111111111111111111110101
	//补码:1111 1111 1111 1111 1111 1111 1111 0110
	//      F    F    F     F   F     F    F   6
	//0xff ff ff f6
	//
	return 0;
}

二、大小端

1.大小端是什么

下面用十六进制数字a来说明

int main()
{
	int a = 0x11223344;
	return 0;
}


可以发现实际上是倒着存的。在这里插入图片描述
44是数据a的低位字节处的数据,而地址由左到右是增高的,44放在了最左边,所以该编译器用的是小端字节序存储。

2.测试编译器用的是大端还是小端

代码如下:

int check_sys()
{
    int a = 1;
	char* p = (char*)&a;
	if (*p == 1)
	{
		return 1;//小端
	}
	else
	{
		return 0;//大端
	}
}
int main()
{
	int ret = check_sys();
    if (ret == 1)
	{
		printf("小端\n");
	}
	else
	{
		printf("大端\n");
	}

	//a在内存中存储的是 00000000000000000000000000000001
	//转化为16进制是 0x 00 00 00 01
	//如果用一个char *类型的指针指向a的地址,再解引用该指针,那么取出的是存储在内存中的第
    //一个字节。如果取出的是01,那么编译器用的是小端存储,因为第一个字节是数字a的较低位,
    //如果取出的是00,那么编译器用的是大端存储
	return 0;
}



三、整形提升

int main()
{
	char a = -1;
	//转化为二进制:10000000000000000000000000000001
	//反码:11111111111111111111111111111110
	//补码:11111111111111111111111111111111
	//
	//由于用的是char类型接收的a,所以被截断了,截断后:11111111
	//由于打印的时候是以%d形式打印,要发生整形提升,提升后:11111111111111111111111111111111
	//反码:11111111111111111111111111111110
	//原码:10000000000000000000000000000001 也就是-1
	//当一个有符号数发生整形提升时,是用符号位的数来补满32个bit,a的符号位是1,所以在前面补1
	signed char b = -1;
	//b与a同理,因为a在没有指定是有符号或无符号时默认为有符号数。
	unsigned char c = -1;
	//转化为二进制:10000000000000000000000000000001
	//反码:11111111111111111111111111111110
	//补码:11111111111111111111111111111111
	//截断:11111111 - c
	//因为c是unsigned,也就是无符号数,所以在整形提升时在前面补的是0 
	//整形提升以后:00000000000000000000000011111111,也就是255
	printf("a=%d,b=%d,c=%d", a, b, c);
	//-1 -1 255
	//打印的是有符号数
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值