深度剖析数据在内存中的存储

1、数据类型介绍

  • char(1) 字符数据类型
  • short(2) 短整形
  • int(4) 整形
  • long(4/8) 长整形
  • long long(8) 更长的整形
  • float(4) 单精度浮点数
  • double(8) 双精度浮点数
    //括号内是各个类型占存储空间的大小
    类型的意义:
    1、使用这个类型开辟内存空间的大小(大小决定了使用范围)
    2、如何看待内存空间的视角(32位/64位)
    (比如:如果在32位环境下,long的存储空间大小是4位,而在64位环境下,存储空间大小是8位)

类型的基本归类

整形类型

char (未定义,取决于编译器本身)
unsigned char
signed char
int(默认为有符号)
unsigned int
signed int
short(默认为有符号)
unsigned short
signed short
long(默认为有符号)
unsigned long
signed long
long long(默认为有符号)
unsigned long long
signed long long

浮点数类型

float
double

构造类型

数组类型 :int [8]、char[6]
结构体类型:struct
枚举类型:enum
联合类型:union

指针类型

int *pi
char *pc
float *pd
void *pv

空类型

void表示空类型(无类型)
通常应用于函数的返回类型、函数的参数、指针类型

2、整形在内存中的存储

一个变量的创建是要在内存中开辟空间的,空间的大小是根据不同的类型而决定的。

原码、反码、补码

计算机中的整形有三种表示方法,即原码、反码和补码
三种表示方法均有符号位和数值位两部分,符号位都是用0表示正,用1表示负,而数值位负整数的三种表示方法各不相同,正整数的三种表示方法都相同。
原码
直接将二进制按照正负数的形式翻译成二进制就可以
反码
除了符号位不变,其次依次按位取反就可以得到了
补码
反码+1就得到了,若想从补码中转化成原码(也是补码变成反码+1=原码)

内存中的存储

调试->窗口->内存
在这里插入图片描述
可以发现在内存中的存储显示的是16进制,但是本质存的还是2进制;发现顺序有点不对劲
ob开头-2进制
o开头-8进制
ox开头-16进制

大小端介绍

大端(存储)模式:是指数据的低位保存在内存的高地址,而数据的高位保存在内存的低地址;–低高高低
小端(存储)模式:是指数据的低位保存在内存的低地址,而数据的高位保存在内存的高地址;–高高低低

百度2015年系统工程师笔试题:

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

include<stdio.h>
int main()
{
	int i = 1;
	char* pi = (char*)&i;//会发生截断,先取出低地址的值
	if (*pi == 1)//解引用取出指针所指向的值
	{
		printf("是小端");
	}
	else
		printf("是大端");
	return 0;
}

以上代码中char *–强制转化一位,为了只访问一个字节。

习题总结

1、

int main()
{
	char a = -1;
	signed char b = -1;
	unsigned char c = -1;
	printf("a=%d\n", a);
	printf("b=%d\n", b);
	printf("c=%d\n", c);
	return 0;
}

这里是引用

2、

int main()
{
	char a = -128;
	char b = 128;
	printf("%u\n", a);
	printf("%u\n", b);
	return 0;
}

在这里插入图片描述
这里是引用

3、

int main()
{
	int i = -20;
	unsigned int j = 10;
	printf("%d\n", i + j);
	return 0;
}

这里是引用

存入时,先整形展开,再截断
打印时,先整形提升
当类型改变时,会发生截断;
当以更大类型打印时,需整形提升,整形提升要看本来存储变量的类型是无符号还是有符号(若该类型为无符号类型,则用0填充,若该类型为有符号类型,则根据存储在内存的补码最高值而定)

3.浮点型在内存中的存储

3.1浮点数存储规则

根据国际标准IEEE(电气和电子工程协会)754,任意一个二进制浮点数v可以表示成下面的形式:

  • V=(-1)^S M 2^E
  • (-1)^S 表示符号位,当S=1时,V为负数,当S=0时,V为正数
  • M表示有效数字,大于等于1,小于2;
  • 2^E表示指数位

举例:
十进制的5.0,写成二进制为101.0,相当于1.01 * 2^2,
那么根据上面V的格式,可以得出S=0,M=1.01,E=2;
十进制的-5.0,写成二进制是-101.0,相当于-1.01 * 2^2,
那么根据上面V的格式,可以得出S=1,M=1.01,E=2;

IEEE 754 规定:
对于32位的浮点数,最高的1位是符号位S,接着的8位是指数E,剩下的23位是有效位
在这里插入图片描述对64位的浮点数,最高位的1位是符号位S,接着的11位是指数E,剩下的52位是有效位
在这里插入图片描述关于M的一些特别规定

  1. 1<=M<=2,其中M可以写成1.xxxxxxx的形式,其中xxxxxxx表示小数部分
  2. 在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍弃,只保留后面的小数部分xxxxxx。
  3. 等到读取的时候,再将第一位的1加上去,这样做的目的是节省1位有效数字,等于可以保存24位有效数字。

关于E的一些特别规定
E为无符号整形(unsigned int)
如果E是8位,它的取值范围为0–255;如果E为11位,它的取值范围为0–2047.但是,科学计数法中的E是可以出现负数的,所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数。对于8位的E,这个是127;对于11位的E,这个中间数是1023。
float: E(真实值)+127(中间数)—>存储
double: E(真实值)+1023(中间数)—>存储

然后,指数E从内存中取出还可以再分成三种情况:

E不全为0或不全为1
根据上述的规则存储,若想将E的真实值求出来,即指数E的存储值减127(或1023),再有效值M前加上第一位的1。

E全为0
这时,浮点数的真实值E等于1-127(1-1023)即为真实值,有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数,这样做是为了表示+和-0,以及接近于0的很小的数字。

E全为1
这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s)

3.2习题演示

int main()
{
	int n = 9;
	float* p = (float*)&n;
	printf("n的值为:%d\n", n);
	printf("p的值为:%f\n", *p);
	*p = 9.0;
	printf("n的值为:%d\n", n);
	printf("p的值为:%f\n", *p);
	return 0;
}

在这里插入图片描述
思考为什么第一个p为0,第二个n是1091567616

这里是引用

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值