整数和浮点数在内存中的存储

1、整数存储

①整数在内存中的存储

在计算机中的数据都是二进制进行存储的,整数的二进制表示形式有原码,反码以及补码。

正数的原码,反码以及补码相同。

对于负数的源码:举个例子-56,其原码,反码以及补码如下所示:

对于整数来说,整数在内存中是以补码的形式进行存储的。使用补码,可以将符号位和数值域统⼀处理;同时,加法和减法也可以统⼀处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。针对负数原码变补码码和补码变原码的都可以通过取反加1来实现。

②大小端字节序

超过⼀个字节的数据在内存中存储的时候,就有存储顺序的问题,按照不同的存储顺序,我们分
为大端字节序存储和小端字节序存储。

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

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

我们常用的 X86 结构是小端模式,而KEIL C51 则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。

判断当前机器是大端字节序存储还是小端字节序存储,代码如下所示:

#include<stdio.h>
int check()
{
	int n = 1;
	char* p = &n;
	return *p;
}
int main()
{
	int ret = check();
	if (ret == 1)
	{
		printf("小端存储\n");
	}
	else
	{
		printf("大端存储\n");
	}
	return 0;
}

 

③有符号整形

常用的有符号整形有long long int , int,short和 char,对于long long int占8个字节也就是64个比特位,最高位为符号位所以范围为-2^63~2^63-1对于unsigned int占4个字节也就是32个比特位,最高位为符号位所以范围为-2^31~2^31-1,对于unsigned  short占2个字节16个比特位没有符号位全是数值位,最高位为符号位所以其能存储的范围为-2^15~2^15-1,unsigned char占一个字节也就是8个比特位,最高位为符号位所以其范围为-2^7~2^7-1

④无符号整形

无符号整形常用的包括unsigned long long int ,unsigned int,unsigned short和unsigned char,其中char类型也就是字符是以ASCII码进行存储的,也可以说是整形。对于unsigned long long int占8个字节也就是64个比特位,没有符号位全是数值位所以范围为0~2^64-1对于unsigned int占4个字节也就是32个比特位,没有符号位全是数值位所以范围为0~2^32-1,对于unsigned  short占2个字节16个比特位没有符号位全是数值位,所以其能存储的范围为0~2^16-1,unsigned char占一个字节也就是8个比特位,没有符号位全是数值位所以其范围为0~2^8-1。需要注意的是用用无符号整形变量作为循环的边界条件时需要注意跳出循环条件是否为随着循环的进行最终会跳出这个循环。

⑤一些整形存储练习题

#include <stdio.h>
int main()
{
	char a = -1;
	//-1的原码:10000000 00000000 00000000 00000001
	//-1的反码:11111111 11111111 11111111 11111110
	//-1的补码:11111111 11111111 11111111 11111111
	//由于要存在char类型的a中,-1存不下所以翻身截断取低八位
	//此时a中所存的内容为11111111
	signed char b = -1;
	//由于要存在char类型的b中,-1存不下所以翻身截断取低八位
	//此时b中所存的内容为11111111
	unsigned char c = -1;
	//由于要存在unsigned char类型的c中,-1存不下所以翻身截断取低八位
	//此时c中所存的内容为11111111
	printf("a=%d,b=%d,c=%d", a, b, c);
	//a,b,c中所存的内容都是一样的进行计算时会对其进行整形提升,%d是以有符号整数来看的
	//a,b,c都会进行整形提升,整形提升是根据其类型来提升的
	//对于a会整形提升为:11111111 11111111 11111111 11111111
	//对于b会整形提升为:11111111 11111111 11111111 11111111
	//对于c会整形提升为:00000000 00000000 00000000 11111111
	//会打印a=-1,b=-1,c=255
	return 0;
}

 运行结果如下:

#include <stdio.h>
int main()
{
	char a = -128;
	//-128原码:10000000 00000000 00000000 10000000
	//-128反码:11111111 11111111 11111111 01111111
	//-128补码:11111111 11111111 11111111 10000000
	printf("%u\n", a);
	//由于a是char类型所以只能存续8个比特位,存低八位
	//所以a中存的值为10000000
	//使用%u对a进行打印时,会对a进行整形提升,整形提升会看a原来的类型
	//a的类型是char是有符号的,补符号位
	//a整形提升为:11111111 11111111 11111111 10000000
	//%u会将11111111 11111111 11111111 10000000看成无符号数
	//通过计算结果是4294967168
	return 0;
}

 运行结果如下:

#include <stdio.h>
int main()
{
	char a = 128;
	//128原码:10000000 00000000 00000000 10000000
	//128反码:10000000 00000000 00000000 10000000
	//128补码:10000000 00000000 00000000 10000000
	printf("%u\n", a);
	//由于a是char类型所以只能存续8个比特位,存低八位
	//所以a中存的值为10000000
	//使用%u对a进行打印时,会对a进行整形提升,整形提升会看a原来的类型
	//a的类型是char是有符号的,补符号位
	//a整形提升为:11111111 11111111 11111111 10000000
	//%u会将11111111 11111111 11111111 10000000看成无符号数
	//通过计算结果是4294967168
	return 0;
}

  运行结果如下:

#include<stdio.h>
int main()
{
	char a[1000];
	int i;
	for (i = 0; i < 1000; i++)
	{
		a[i] = -1 - i;
	}
	//a是字符数组,所以存档是ASCII码值
	//这些值以此是是-1,-2,-3,-4...,-127,-128,127,126,126,125...,4,3,2,1,0,1,2...127,-128,...-2,-1,0,....
	printf("%d", strlen(a));
	//strlen(a)求的是字符\0之前的个数,也就是ASCII码值为0之前的个数,有255个,所以输出255
	return 0;
}

运行结果如下:

#include <stdio.h>
unsigned char i = 0;
int main()
{
	for (i = 0; i <= 255; i++)
	{
		printf("hello world\n");
	}//unsigned char所能存储的是0~255
	//当i为255进行加1操作i又会变为0,所以该程序会造成死循环
	//死循环
	return 0;
}

运行结果如下:(死循环打印)

#include <stdio.h>
#include<Windows.h>
int main()
{
	unsigned int i;
	for (i = 9; i >= 0; i--)
	{
		printf("%u\n", i);
		Sleep(1000);
	}//死循环
	//9,8,7,6,5,4,3,2,1,0,...
	return 0;
}

#include <stdio.h>
//在X86环境 ⼩端字节序
int main()
{
	int a[4] = { 1, 2, 3, 4 };
	int* ptr1 = (int*)(&a + 1);
	int* ptr2 = (int*)((int)a + 1);
	printf("%x,%x", ptr1[-1], *ptr2);
	//4 2000000
	return 0;
}

 2、浮点数存储

浮点数家族包括: float、double、long double 类型。
浮点数表示的范围: float.h 中定义

 E为一个无符号整数这意味着,如果E为8位,它的取值范围为0~255;如果E为11位,它的取值范围为0~2047。但是,科学计数法中的E是可以出现负数的,所以IEEE754规定,存入内存时E的真实值必须再加上⼀个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。比如,2^10的E是10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001

#include <stdio.h>
int main()
{
	int n = 9;
	float* pFloat = (float*)&n;
	printf("n的值为:%d\n", n);//以整形的方式存,整形的方式从内存中拿所以是9
	printf("*pFloat的值为:%f\n", *pFloat);
	//整数9存在内存的二进制位:00000000 00000000 00000000 00001001
	//*pFloat虽说会访问4个字节,但其看待内存的方式与整形是不同的
	//*pFloat会将0 00000000 00000000000000000001001
	//E全为0所以就会将其当成一个非常小的数,所以打印出来的就是0
	*pFloat = 9.0;
	//在n的空间里以浮点数的方式存9.0
	//(-1)^0*1.001*2^3
	// E=130
	//此时内存中存放是:0 10000010 00100000000000000000000
	printf("num的值为:%d\n", n);//以浮点数的方式存,以整形的方式拿,所以是一个很大的数
	//得到的是1091567616
	printf("*pFloat的值为:%f\n", *pFloat);//以浮点数的方式存,以浮点数的方式拿所以是9.0
	return 0;
}

本篇文章主要介绍了整数和浮点数在内存中的存储方式,还举了一些例子,以便能够更好地理解整数和浮点数在内存中的存储。感谢大家观看,如有错误不足欢迎大家批评指正!!!

  • 20
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值