【C语言】整形在内存中的存储

1、整形在内存中的存储

1.1 原码、反码、补码

计算机中整数有三种二进制表示方法,分别是原码、反码、补码

三种表示方法由符号位和数值位构成符号位用0表示正数,1表示负数。

整形数据在内存中存放的是补码

正数的原码、反码、补码相同

负数的补码=原码的符号位不变,其它位按位取反得到反码,反码+1得到补码

//10
//原码=反码=补码
//00000000 00000000 00000000 00001010
//-10
//10000000 00000000 00000000 00001010 原码
//11111111 11111111 11111111 11110101 反码
//11111111 11111111 11111111 11110110 补码 

为什么整形在内存中存放的是补码?

在计算机系统中,数值一律用补码来表示和存储,原因在于使用补码,可以将符号位和数值位统一处理,同时,加法和减法也可以统一,CPU只有加法。

1.2 大小端

1.2.1 什么是大小端

大端存储模式,是指数据的高位保存在内存的低地址处,数据的低位保存在高地址处。

小端存储模式,是指数据的低位保存在内存的低地址处,数据的高位保存在高地址处。

 1.2.2 为什么要有大小端

 一个数据如果超过一个字节存放在内存里,有存储顺序的问题

因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应者一个字节,一个字节为8bit,但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的int型(取决于编译器)。对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么。然存在着一个如何将字节安排的问题,因此导致了大小端的存储模式。

1.2.3 大小端判断

请简述大端字节序和小端字节序的概念,设计一个小程序来判断当前机器的字节序。

int check_sys()
{
	int a = 1;
	//00000000 00000000 00000000 00000001
	//0x 00 00 00 01
	//小端存储 01 00 00 00
	//大端存储 00 00 00 01
	//char* p = (char*)&a;//强制转换成char*
	//char*的指针解引用可以访问一个字节
	//&a 第一个字节地址保存在char*的指针中
	//if (*p == 1)
	//{
	//	return 1;//小端
	//}
	//else
	//{
	//	return 0;//大端
	//}

	//return *p;
	return *(char*)&a;//先取地址 取地址后强制类型转换成char*地址 解引用访问一个字节
}
int main()
{
	int ret=check_sys();
	if (ret == 1)
	{
		printf("小端\n");
	}
	else
	{
		printf("大端\n");
	}
	return 0;
}

1.3 相关练习题

//练习1
int main()
{
	char a = -1;
	signed char b = -1;
	unsigned char c = -1;
	printf("a=%d,b=%d,c=%d", a, b, c);
	return 0;
}
//结果 -1 -1 255
//解析
int main()
{
	char a = -1;
	//-1
	//10000000 00000000 00000000 00000001
	//11111111 11111111 11111111 11111110
	//11111111 11111111 11111111 11111111 补码
	// 有符号char a里存放低八个比特位
	//11111111
	//以%d的形式打印 打印一个整形 有符号char 不够一个整形 整形提升
	//当打印a的时候要发生整形提升
	//整形提升补的是原来变量的符号位
	//11111111 11111111 11111111 11111111 提升之后的补码
	//打印的是有符号数 补码->原码
	//10000000 00000000 00000000 00000001

	signed char b = -1;
	unsigned char c = -1;
	//-1
	//10000000 00000000 00000000 00000001
	//11111111 11111111 11111111 11111110
	//11111111 11111111 11111111 11111111 补码
	//11111111 c里存放
	//c是%d的形式打印 打印一个整形 要整形提升
	//c是unsigned char 高位补0
	//00000000 00000000 00000000 11111111 补码
	//高位是0 0是整数 原码反码补码相同

	printf("a=%d,b=%d,c=%d", a, b, c);
	return 0;
}
//练习2
int main()
{
	char a = -128;
	printf("%u\n", a);
	return 0;
}
//结果 4294967168
int main()
{
	char a = 128;
	//-128
	//10000000 000000000 00000000 100000000
	//11111111 111111111 11111111 011111111
	//11111111 111111111 11111111 100000000
	//10000000发生截断 保留低八个比特位
	//%u 指的是打印无符号整数
	// 整形
	//11111111 111111111 11111111 100000000
	//%u 补码=原码
	printf("%u\n", a);
	return 0;
}
//练习3
int main()
{
	char a = 128;
	printf("%u\n", a);
	return 0;
}
//结果 4294967168
int main()
{
	char a = 128;
	//128
	//00000000 000000000 00000000 100000000
	//10000000-a发生截断 保留低八个比特位
	//按照%u打印 对a进行整形提升 指的是打印无符号整数
	// 整形
	//11111111 111111111 11111111 100000000
	//%u 补码=原码
	printf("%u\n", a);
	return 0;
}
//练习4
int main()
{
	int i = -20;
	unsigned int j = 10;
	printf("%d\n", i + j);
	return 0;
}
int main()
{
	int i = -20;
	//-20
	//100000000 00000000 00000000 00010100
	//111111111 11111111 11111111 11101011
	//111111111 11111111 11111111 11101100 -20的补码
	
	unsigned int j = 10;
	//10
	//000000000 00000000 00000000 00001010
	//-20+10
	//000000000 00000000 00000000 00001010
	//111111111 11111111 11111111 11101100
	//111111111 11111111 11111111 11110110 补码 %d有符号整数
	//111111111 11111111 11111111 11110101
	//100000000 00000000 00000000 00001010
	printf("%d\n", i + j);
	//111111111 11111111 11111111 11110110 补码 %d有符号整数
	//111111111 11111111 11111111 11110101
	//100000000 00000000 00000000 00001010
	return 0;
}
//练习5
int main()
{
	unsigned  int i;
	for (i = 9; i >= 0; i--)
	{
		printf("%u\n", i);
	}
	return 0;
}
//无符号整形最小值是0 没有符号位
//9 8 7 6 5 4 3 2 1 0 -1
//-1对于无符号整形来说是32个比特位都是1
//-1
//10000000 00000000 00000000 00000001 原码
//11111111 11111111 11111111 11111110 反码
//11111111 11111111 11111111 11111111 补码
//编译器不认为补码的符号位是负数,理解成正数
//编译器按照正整数打印
//打印从9-0-4294967295-0-4294967295-0循环下去
//练习6
int main()
{
	char a[1000];
	int i;
	for (i = 0; i < 1000; i++)
	{
		a[i] = -1 - i;
	}
	printf("%d", strlen(a));
	return 0;
}
//数组a中元素
//-1 -2 -3 -128 127 126 ....3 2 1 0 -1 -2..........
strlen是求字符串长度的 找的是\0的位置,统计\0之前出现多少个字符
//'\0'的ASCII码值是0
//数组每个元素char类型的值,有符号的char表示值的范围-128-127
//值的范围是 0->127->-128->-1->0
//字符串为255个(128+127)
//练习7
unsigned char i = 0;
int main()
{
	for (i = 0; i <= 255; i++)
	{
		printf("hello world\n");
	}
	return 0;
}
//死循环打印hello world
//无符号的char取值范围是0-255

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值