c语言进阶部分详解(数据在内存中的存储)

news2025/2/12 11:06:37

大家好,今天要进行梳理的内容是数据在内存中的存储相关内容。

在C语言中,数据在内存中的存储是一个非常重要的概念。了解数据在内存中的存储方式可以帮助我们更好地理解程序的执行过程,优化内存使用,提高程序的性能。


目录

一.数据类型介绍

1.类型的基本归类 

二.整形在内存中的存储 

1 原码、反码、补码 

2. 大小端介绍 

3.利用代码判断大小端

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

1.浮点数存储规则 

2.练习 

第二个结果

第三个结果


一.数据类型介绍

我们经常见到和使用的数据类型如下 

char
short
int
long
long long
float
double
//字符数据类型
//短整型
//整形
//长整型 (也可写作long int)
//更长的整形 (也可写作long long int)
//单精度浮点数
//双精度浮点数

需要注意的是:学习过Java的同学们知道有String(字符串类型),但是c语言没有,我们使用字符数组来代替(char arr [ ]).

而对于上述类型所占字节大小,各位可使用sizeof关键字来进行查看

1.类型的基本归类 

整型: 


其中char为整型:在C语言中,char类型可以用来表示字符,每个字符都对应一个整数值。例如,字符'A'对应的整数值是65,字符'a'对应的整数值是97。这是因为C语言使用了ASCII编码,将字符映射为整数值
 


浮点型: 


 构造类型:

  •  数组类型
  •  结构体类型 struct
  •  枚举类型 enum
  •  联合类型 union

指针类型:

  • int *pi;
  • char *pc;
  • float* pf;
  • void* pv;

空类型:

空类型(void)是一种特殊的类型,表示“无类型”或“没有值”。void类型通常用于以下几个方面:

  1. 函数返回类型:当函数不返回任何值时,可以将其返回类型声明为void。例如,一个不返回值的函数可以定义为void func()

  2. 函数参数类型:当函数不接受任何参数时,可以将其参数列表声明为void。例如,一个不接受参数的函数可以定义为void func(void)

  3. 指针类型:void指针是一种通用指针类型,可以指向任何类型的数据。void指针可以通过强制类型转换(类型转换操作符)转换为其他类型的指针。例如,void* ptr可以指向任何类型的数据。

  4. 函数指针类型:void函数指针可以指向任何类型的函数。例如,void (*funcPtr)()是一个指向不返回值的函数的指针。

需要注意的是,void类型的变量不能直接声明和初始化,因为它没有具体的值。它只能用于函数返回类型、函数参数类型或指针类型的声明


二.整形在内存中的存储
 

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

而且整型数据在内存中的存储方式涉及到原码、反码和补码的概念
 

1 原码、反码、补码
 

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

  • 原码:原码是整数的二进制表示形式,最高位表示符号位,0表示正数,1表示负数。例如,+5的原码为00000101,-5的原码为10000101
  • 反码:反码是对原码按位取反(符号位除外)得到的结果。正数的反码与原码相同,负数的反码是将原码中的1变为0,0变为1。例如,+5的反码为00000101,-5的反码为11111010
  • 补码:补码是对反码加1得到的结果。正数的补码与原码相同,负数的补码是将反码中的1加1。例如,+5的补码为00000101,-5的补码为11111011

对于整型来说,数据存放内存中其实存放的是补码
因为:计算机使用补码表示有符号整数可以解决0的表示问题以及减法运算的简化,原码和反码没有办法解决多个0的问题(10000000和00000000均可表示0)


2. 大小端介绍
 

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

 

这里我们可以看到,位于数据低位的44在地址里也是低位,所以VS019是小端存储 

3.利用代码判断大小端

我们当然也可以写一段代码来判断大小端 

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

  1. 在函数check_sys()中,定义了一个整型变量i并初始化为1。
  2. 然后使用类型转换,将i的地址强制转换为char类型的指针,并通过解引用操作符*访问该地址所指向的字节值(即内存中最低处的值)。
  3. 返回该字节值,即返回i的最低有效字节。
  4. main()函数中,调用check_sys()函数,并将返回值赋给变量ret
  5. 使用条件语句判断ret的值,如果等于1,则输出"小端",表示当前系统是小端序;如果等于0输出"大端",表示当前系统是大端序

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

1.浮点数存储规则 

 根据国际标准IEEE,任意一个二进制浮点数V可以表示成下面的形式:

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

eg:

十进制的5.0,写成二进制是 101.0 ,相当于 1.01×2^2
按照上面V的格式,可以得出S=0,M=1.01,E=2
十进制的-5.0,写成二进制是 -101.0 ,相当于 -1.01×2^2 。那么,S=1,M=1.01,E=2


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

 

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


IEEE 754对有效数字M和指数E,还有一些特别规定

1≤M<2 ,也就是说,M可以写成 1.xxxxxx 的形式,其中xxxxxx表示小数部分。
IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分。比如保存1.01的时候,只保存01,等到读取的时候,再把第一位的1加上去。这样做的目的,是节省1位有效数字

以32位浮点数为例,留给M只有23位,将第一位的1舍去以后,等于可以保存24位有效数字

而对于E的情况就更加复杂了

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

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

  1. 全为0

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

     2.全为1

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

    3.不全为1或0

这时,浮点数就采用下面的规则表示,即指数E的计算值减去127(或1023),得到真实值,再将
有效数字M前加上第一位的1。
比如:
0.5(1/2)的二进制形式为0.1,由于规定正数部分必须为1,即将小数点右移1位,则为
1.0*2^(-1),其阶码为-1+127=126,表示为
01111110,而尾数1.0去掉整数部分为0,补齐0到23位00000000000000000000000,则其二进
制表示形式为:  0 01111110 00000000000000000000000
 


2.练习 

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

结果倒是让人大跌眼镜:


 第一个和最后一个大家应该没有疑问,那我们主要来分析第二个和第三个结果

第二个结果

整型9的补码是00000000000000000000000000001001 

从float指针的角度来看:0 00000000 00000000000000000001001  其中S=0,E=1-127,M=00000000000000000001001,符合上面E全是0的情况,结果非常非常小,所以是0.000000

第三个结果

9.0即是1001.0(二进制后几位)-> 1.001*2^3-> S=0   E=3+127   M=1.001

M的有效位是001,后面要补全20个0

最终二进制的呈现:0 10000010 001 0000 0000 0000 0000 000(刚好就是1091567616

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/864289.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

5.0SMDJ24CA 瞬态抑制TVS二极管 可过4kV 2Ω测试

瞬态概述 浪涌描述的是存在于电源或信号线上uS级以上的脉冲。通常浪涌产生于雷击或开关瞬变能量。雷击能量可能是由于直击雷或感应雷作用于系统所产生的瞬变能量&#xff0c;开关瞬变能量通常由于配电系统的电源切换&#xff0c;或是负载的变化导致。 雷击浪涌测试目的 GB/T …

QT中的PRO文件怎么进行相关的信息的注释?

小白学开发之QT下的PRO文件怎么进行注释&#xff0c;以及Pro文件的作用 Hello大家好&#xff0c;这里是程序员小白学开发&#xff0c;我是一个刚入门QT的初学者&#xff0c;晕乎晕乎的&#xff01;希望能够随时随地将自己所学的知识分享给大家&#xff0c;带着大学从零基础开始…

测试设计规范:优秀实践的全面指南

测试设计规范是一个定义了与测试项目相关的测试条件、详细的测试方法和高级测试用例的文档。它确定了要运行哪些测试套件和测试用例&#xff0c;以及要跳过哪些。 使用测试设计规范&#xff0c;可以简化对当前测试周期的理解。这个文档回答了像“我们在做什么?”&#xff0c;…

springcloud3 springcloud stream的学习以及案例(了解)

一 springcloud stream的作用 1.1 springcloud stream作用 stream屏蔽底层消息中间件的差异&#xff0c;降低切换成本&#xff0c;统一消息的编程模型。 stream中的消息通信模式遵循了“发布-订阅”模式。 1.2 Binder作用 通过定义绑定器Binder作为中间层&#xff0c;实现…

基于DEM tif影像的插值平滑和tif纹理贴图构建方法

准备数据是一个10米分辨率的Tif影像&#xff0c;直接用于生成DEM会十分的不平滑。如下图所示&#xff0c;平滑前后的对比效果图差异&#xff1a; 基于ArcGIS的DEM平滑插值 等值线生成&#xff08;指定加密间距&#xff09; 平滑线&#xff08;指定平滑容差平滑等高线&#xff0…

jackson库收发json格式数据和ajax发送json格式的数据

一、jackson库收发json格式数据 jackson库是maven仓库中用来实现组织json数据功能的库。 json格式  json格式一个组织数据的字符文本格式&#xff0c;它用键值对的方式存贮数据&#xff0c;json数据都是有一对对键值对组成的&#xff0c;键只能是字符串&#xff0c;用双引号包…

python爬虫——爬虫伪装和反“反爬”

前言 爬虫伪装和反“反爬”是在爬虫领域中非常重要的话题。伪装可以让你的爬虫看起来更像普通的浏览器或者应用程序&#xff0c;从而减少被服务器封禁的风险&#xff1b;反“反爬”则是应对服务器加强的反爬虫机制。下面将详细介绍一些常见的伪装和反反爬技巧&#xff0c;并提…

ATF(TF-A)安全通告 TFV-9 (CVE-2022-23960)

ATF(TF-A)安全通告汇总 目录 一、ATF(TF-A)安全通告 TFV-9 (CVE-2022-23960) 二、CVE-2022-23960 一、ATF(TF-A)安全通告 TFV-9 (CVE-2022-23960) Title TF-A披露通过分支预测目标重用&#xff08;branch prediction target reuse&#xff09;引发的前瞻执行处理器漏洞 CV…

2000-2022年全国各地级市绿色金融指数数据

2000-2022年全国各地级市绿色金融指数数据 1、时间&#xff1a;2000-2022年 2、来源&#xff1a;来源&#xff1a;统计局、科技部、中国人民银行等权威机构网站及各种权威统计年鉴&#xff0c;包括全国及各省市统计年鉴、环境状况公报及一些专业统计年鉴&#xff0c;如 《中国…

工厂老化设备维护的重要性及如何维护老化设备?

工业领域的老化设备问题日益凸显&#xff0c;对于保持生产稳定和效率至关重要。本文将探讨工厂老化设备维护的重要性&#xff0c;并介绍如何通过PreMaint设备数字化平台实现对老化设备的高效维护&#xff0c;从而确保工厂持续高效运转。 一、工厂老化设备的重要性 随着时间的推…

Flutter实现倒计时功能,秒数转时分秒,然后倒计时

Flutter实现倒计时功能 发布时间&#xff1a;2023/05/12 本文实例为大家分享了Flutter实现倒计时功能的具体代码&#xff0c;供大家参考&#xff0c;具体内容如下 有一个需求&#xff0c;需要在页面进行显示倒计时&#xff0c;倒计时结束后&#xff0c;做相应的逻辑处理。 实…

【Spring专题】Bean的声明周期流程图

前言 我向来不主张【通过源码】理解业务&#xff0c;因为每个人的能力有限&#xff0c;甚至可能会因为阅读错误导致出现理解上的偏差&#xff0c;所以我决定&#xff0c;还是先帮大家【开天眼】&#xff0c;先整体看看流程图&#xff0c;好知道&#xff0c;Spring在写源码的过…

山东Certum公网IP证书申请

Certum作为欧洲第一个通过WebTrust的CA认证机构&#xff0c;一直致力于为用户提供高质量的数字证书服务。WebTrust是一种全球认可的数字证书认证标准&#xff0c;它确保了数字证书颁发机构的操作符合严格的标准和程序。Certum通过WebTrust的认证&#xff0c;证明了其数字证书服…

Practices9(双指针)|283. 移动零、11. 盛最多水的容器、15. 三数之和

283. 移动零 1.题目&#xff1a; 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 示例 1: 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,…

豪越HYDO智能运维助力智慧医院信息化建设

随着国家政策的推动与支持&#xff0c;医疗行业信息化应用不断普及&#xff0c;大数据、AI、医疗物联网等技术的应用&#xff0c;快速推动了电子病历、智慧服务、智慧管理的智慧医院建设和医院信息标准化建设&#xff0c;通过不断探索创新“智慧医院”服务模式&#xff0c;实现…

中国首份仿生机器人产业全景报告发布!大模型带来加速度,三大指标决定竞争格局

AGI火热发展&#xff0c;让仿生机器人的实现补全了最后一块重要拼图。 一直以来&#xff0c;仿生机器人都代表人类对于科技的一种终极想象&#xff0c;备受产业圈热捧。 马斯克、雷军等&#xff0c;纷纷押注这一赛道。特斯拉全尺寸仿生机器人Optimus、小米全尺寸通用人形机器…

资深测试员才知道的五个行业秘密

作为一名资深测试员&#xff0c;总有一些平时难以诉说的行业秘密&#xff0c;我也不例外。也许这些秘密你认可&#xff0c;也许你嗤之以鼻&#xff0c;但不管如何&#xff0c;我都希望能给你带来一丝感悟&#xff0c;更深的认识测试&#xff0c;并走得更远。 1、手工测试不可替…

【Linux】网络基础2

文章目录 网络基础21. 应用层1.1 协议1.2 HTTP 协议1.2.1 URL1.2.2 urlencode和urldecode1.2.3 HTTP协议格式1.2.4 HTTP的方法1.2.5 HTTP的状态码1.2.6 HTTP 常见的header1.2.7 最简单的HTTP服务器 2. 传输层2.1 端口号2.1.1 端口号范围划分2.1.2 认识知名端口号2.1.3 netstat2…

RFID技术应用于服饰市场

RFID技术应用于服饰市场 RFID技术已广泛应用于服饰制造加工行业&#xff0c;为企业提供了许多实用的解决方案。下面是一些常见的应用场景&#xff1a; 库存管理&#xff1a;RFID标签可以被缝制或附着在服装上&#xff0c;通过RFID读写器进行扫描。企业可以实时跟踪和管理库存…

配置中心替换测试设计分享

一、背景 项目后端服务开始一直使用Apollo配置中心(携程开发)进行配置管理&#xff0c;由于公司自研了配置中心B&#xff0c;为了后续方便管理和降本增效&#xff0c;后端服务使用的配置需要由Apollo配置中心切换到自研配置中心B。后续不再使用Apollo配置。 替换前架构&#x…