当前位置: 首页 > news >正文

C语言(25)

一.数据在内存中的存储

1.整数在内存中的存储

整数在内存中以二进制的形式储存,分别为原码,补码,反码

有符号的整数,在上述三种形式都有符号位和数值位两个部分,符号位为0是正数,1是负数,最高位的一位是符号位,剩余的都是数值位

正整数的原码,补码,反码都一样

负整数的原码补码和反码都各不相同

原码:直接将数值按照正负数的形式变成二进制就是原码

反码:符号位不变,数值位取反

补码:反码+1

注意,整数存放数值的补码形式

2.大小端字节序和字节判断

实例一

2.1大小端字节序存储

大端字节序存储:将数据的低位字节放在内存的高位地址上,高位字节放在内存的低位地址上

小端字节序存储:将数据的低位字节放在内存的低位地址上,高位字节放在内存的高位地址上

所以实例一是小端字节序存储

2.2为什么有大小端字节序存储

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

例如:⼀个 16bit的 short 型 x ,在内存中的地址为0x0010, x 的值为 0x1122,那么0x11为⾼字节, 0x22 为低字节。对于⼤端模式,就将0x11放在低地址中,即 0x0010 中,0x22 放在⾼地址中,即 0x0011 中。

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

2.3练习

2.3.1

如何判断系统是大端字节序存储还是小端字节序存储?

实例二

注释:取数据的首地址进行char*形式的转化,然后对其进行解应用看是否是1来进行判断

2.3.2
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;
}

运算一下,算算答案,下列是运行结果

解析:

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

求a的打印数值是多少

运行结果以及解析:

2.3.4

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

求a经过无符号打印的数值是多少

下列是解析和结果:

2.3.5
int main()
{
	char a[1000];
	int i;
	for (i = 0; i < 1000; i++)
	{
		a[i] = -1 - i;
	}
	printf("%d", strlen(a));
	return 0;
}

求出结果

下列是解析和运行结果

解析:char默认是有符号的char,也就是signed char类型,它的有效值是从-128到127,所以数值的变化是-1,-2,-3,-4,...-128,127,126,...0,-1,-2,....一直这么循环。strlen则是一直到\0就会停下,,所以最终结果是255。

2.3.6
unsigned char i = 0;
int main()
{
	for (i = 0; i <= 255; i++)
	{
		printf("hello world\n");
	}
	return 0;
}

想想运行结果

下列是运行结果以及解析:

 解析:运行结果陷入无限循环,因为unsigned char类型范围是从0~255,并且数值变化是循环变化,所以i的值是不会大于255,所以无限循环。

2.3.7
int main()
{
 unsigned int i;
 for(i = 9; i >= 0; i--)
 {
 printf("%u\n",i);
 }
 return 0;
}

想想运算结果

下列是结果和解析:

解析:依旧是陷入了无限循环的结果,因为unsigend char的数值一定大于0,所以i<=0一直成立。

2.3.8
#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);
 return 0;
}

想想运行结果

下列是运行结果:

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

常见的浮点数:3.14159,1E10(意思是1.0*10**10)等,浮点数类型有float、double、long double类型

浮点数表示的范围在float.h中定义

3.1引子

int main()
{
	int n = 9;
	float* pfloat = (float*)&n;
	printf("%d\n", n);
	printf("%f\n", pfloat);

	*pfloat = 9.0;
	printf("%d\n", n);
	printf("%f\n", pfloat);
	return 0;
}

想一下运行结果会是什么

上述的运行结果是否和你想的一样呢

上一个例子说明了整数和浮点数在内存的存储是不一样的。

3.2浮点数的存储

根据国际标准IEEE(电⽓和电⼦⼯程协会)754,任意⼀个⼆进制浮点数V可以表示成下面的形式:

例如:十进制的10.5转化成上述的形式的话,10.5化成二进制是1010.1,进而转化成1.0101*2^3,所以最后的形式就是(-1)^0*1.0101*2^3

(S=0;M=1.0101;E=3)

所以对于浮点数的存储,只需要存储S,M,E的相关值就可以表示出浮点数

IEEE 754规定:

对于32位的浮点数,最高的1位存储符号位S,接着的8位存储指数E,剩下的23位存储有效数字M

对于64位的浮点数,最高的1位存储符号位S,接着的11位存储指数E,剩下的52位存储有效数字M

3.2.1浮点数存的过程

对于数字M

因为1<=M<2

IEEE754规定,在计算机内部保存M时,默认这个数的第⼀位总是1,因此可以被舍去,只保存后面的 xxxxxx部分。比如保存1.01的时候,只保存01,等到读取的时候,再把第⼀位的1加上去。

这样做的目的,是节省1位有效数字。以32位浮点数为例,留给M只有23位,将第⼀位的1舍去以后,等于可以保存24位有效数字。

对于数字E

首先,E是一个无符号整数

这就意味着,如果E为8位,它的取值范围就是0~255;如果E为11位,则取值范围是0~2047.

但是E的取值是可以为负数的,比如0.1中E就是-1,所以IEEE 754规定,存入内存时E的真实值必须再放入一个中间值,对于8位的E,中间值是127,对于11位的E,中间值是1023.

所以如果8位的E的真实值是5,则存入内存的值就是5+127=132,换算成二进制就是10000100

3.2.2浮点数取的过程

指数E从内存中取有三种情况

E不全为0或者不全为1(常规情况)

这时,浮点数就采用下面的规则表示,即指数E的计算值减去127(或1027),得到真实值,再在前面加上1作为第一位

E全为0

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

E全为1

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

例子:

int main()
{
	float a = 5.5f;
	//S=0
	//M=1.011
	//E=2
	return 0;
}

自己推算的话就是0 1000000 101100000000000000000000

整理一下就是 0100 0000 1011 0000 0000 0000 0000 0000

                       40                 b0                 00            00 

就是下面的结果

相关文章:

  • Python中的简单爬虫
  • JS—垃圾回收机制:5分钟掌握Java和JavaScript垃圾回收机制
  • 华为云在智能制造的创新技术
  • 第三百七十五节 JavaFX教程 - JavaFX表视图
  • axis=0 和 axis=1的区分设置matplotlib正常显示中文和负号
  • Debezium日常分享系列之:Debezium 3.1.0.Beta1发布
  • Redisson 实现分布式锁源码浅析
  • Linux文件IO——缓冲区磁盘上的文件管理
  • 微信小程序刷题逻辑实现:技术揭秘与实践分享
  • 电子电子架构 --- 车载ECU信息安全
  • 68.Harmonyos NEXT 图片预览组件应用实践(一):相册与社交场景
  • 从零开始探索C++游戏开发:性能、控制与无限可能
  • Unity中解锁图片像素点,动态闭合轨迹检测
  • 实验三 Python 数据可视化 Python 聚类-K-means(CQUPT)
  • C语言从入门到精通
  • 征程 6 基于 Linux 和 Node-Locked License 配置 DSP 开发环境
  • 【WEB APIs】DOM-事件基础
  • 【服务器知识】Nginx路由匹配规则说明
  • 详解SQL数据更新功能
  • C# 集合
  • 武康大楼再开发:一栋楼火还不够,要带火街区“朋友圈”
  • 爬坡难下坡险,居民出行难题如何解?
  • 中国首艘海洋级智能科考船“同济”号试航成功,可搭载水下遥控机器人
  • 上海虹桥国际咖啡文化节开幕,推出茶咖文化特色街区、宝妈咖啡师培训
  • 最高检公布一起离婚纠纷典型案例:推动离婚经济补偿制度落实
  • 农行回应“病重老人被要求亲自取钱在银行去世”:全力配合公安机关调查