掌握C语言内存布局:数据存储的智慧之旅

大家好,这里是小编的博客频道
小编的博客:就爱学编程

很高兴在CSDN这个大家庭与大家相识,希望能在这里与大家共同进步,共同收获更好的自己!!!

目录

  • 引言
  • 正文
    • 一、数据类型介绍
      • 1.内置类型
      • 2.自定义类型
      • 3.指针类型
      • 4.空类型(void)
    • 二、数据在内存中的存储规则
      • 1.整型数据在内存中的存储
        • 原码 、反码 、补码
      • 2.整型数据的运算与打印
        • (1)占位符
        • (2)数据范围
        • (3)整型提升
        • (4)数据截断
    • 三、大小端介绍
      • 1.来历
      • 2.模式介绍及效果
      • 3.模式判断
  • 快乐的时光总是短暂,咱们下篇博文再见啦!!!不要忘了,给小编点点赞和收藏支持一下,在此非常感谢!!!

引言

本文主要讲述了数据在内存中的存储位置,存储方法以及如何读取内存中的数据。如果你对其有困惑,不妨好好阅读,也许会有新的体会和感悟。
在这里插入图片描述


那接下来就让我们开始遨游在知识的海洋!

正文


一、数据类型介绍

1.内置类型

整型家族

家族成员
int
char
unsigned.int
short.int
long.long
unsigned.short
signed.short
unsigned.long.long
signed.long.long
signed.int
unsigned.char
signed.char

疑惑点:为什么char类型属于整型家族?
解释:这是因为char类型的数据在存储的时候,是以它的ASCLL值进行存储的,本质是一个整型。

浮点型家族

家族成员
float
double

注意:浮点型都是有符号的。


2.自定义类型

组成
数组
结构体.struct
枚举.enum
联合体.union

3.指针类型

组成
一级指针
用来存放内置数据类型变量的地址
二级指针
用来存放一级指针变量的地址

4.空类型(void)

常用于表示函数不需要参数
例:

#include<stdio.h>
int main(void) {
	printf("hello,world!");
	return 0;
}

运行结果:
在这里插入图片描述

当然,这常适用于非主函数


二、数据在内存中的存储规则

符号位:对于一个有符号的的数来说,最高位就是符号位,c语言中规定1表示负,0表示正。

1.整型数据在内存中的存储

原码 、反码 、补码

原码
把一个十进制数直接转化为它的二进制,就是这个数的原码。

反码
正数:还是原码
负数:符号位不变,其他位按位取反

补码
正数:还是原码
负数:反码+1

signed.int
负数.十进制
原码.二进制
符号位不变,其他位按位取反
反码
加1
补码
正数.十进制

我们要注意:

  • 对于有符号整型数据:只有屏幕上打印的是原码,而在内存中进行存储和表示的都是补码。

为什么?

序号原因
1.使用补码,可以将符号位和数值域统一处理
2.加减法也可以统一用加法处理(CPU只有加法器)

凭什么这么说?我们可以用一个简单的例子佐证我们的说法
例:

  • 写一个代码打印-1+1的结果

代码:

#include<stdio.h>
int main() {
	printf("%d", -1 + 1);
	return 0;
}

运行结果:
在这里插入图片描述

思考讨论
到这里,你可能会想:这不就理应如此吗?但事实上,这是我们c语言设计好的用补码进行运算的结果。不信?你看:如果我们用原码进行计算,我们会惊奇的发现发现:最后的打印结果应为-2。但是这就与常理违背了,-1 + 1 == -2 , 离之大谱!

所以通过这个例子,我们就不难发现:

  • 对于整型数据来说,只有屏幕上打印的是原码,而在内存中进行存储和表示的都是补码的智慧和原因
序号注意
1.原码,反码,补码的概念主要针对有符号的整型家族(signed int或int)类型的数据,而对于其他类型的数据,有其相应的存储方式
2.特殊地:我们把无符号的整型家族可以看做正数(有符号的数)进行处理,只不过这个正数没有符号位

2.整型数据的运算与打印

但是,掌握了以上的知识点之后,我们其实还并不能完全预见和理解整型数据运算屏幕上打印的结果,还得掌握一些占位符的作用,整型提升数据截断数据范围

(1)占位符
占位符作用
%d打印有符号整型数据
%u、%zd打印无符号整型数据

例:

#include<stdio.h>
int main() {
	int a = 2147483647;
	int b = 1;
	printf("%d %u", a + b, a + b);
	return 0;
}

运行结果:
在这里插入图片描述

思考:为什么同样是a + b,打印的结果确一正一负呢?

  • 这里其实涉及了后文要讲的数据范围,但我们通过这个例子依旧是能够感受到占位符不同所带来的不同打印结果,该题我们在后文再进一步剖析。

(2)数据范围

我们知道:

1.每个数据类型都有其对应的字节长度,1字节 == 8bit 位

详见:

数据类型字节
char1
short(int)2
(long) int4
float4
long long8
double8

那这些bit位是用来干嘛的呢?

2.实际上,这些bit位就是用来存放数字1或0来表示数据大小的。由此我们可以想到:那既然表示数据大小的位数是有限的,那每个类型的数据大小也应该是在一个范围内的。

详见:

数据类型范围
char-128 ~ 127, 0 ~ 255
short(int)- 2^15 ~ 2^15 - 1, 0 ~ 2^16 - 1
(long) int- 2^31 ~ 2^31 - 1, 0 ~ 2^32 - 1

注:有负号的为有符号数据类型数据的范围


那如果一个数据超过了其范围,怎么计算?

我们可以用圆环的思想去考虑:

  • 每一个无符号的数据类型从大到小都是bit位全0–>bit位全1,而到了最大的时候,也就是bit位全1,再加1就会发生数据越位,所有bit位变成全0,然后再由bit全0–>bit位全1,构成了一个头尾相交的圆环。

以unsigned char为例:

11111100
11111111
00000000

等价于:

12
225
0

而每一个符号的数据类型从大到小都是bit位全0–>bit位除了首位全1,而到了最大的时候,也就是bit位除了首位全1,再加1就会变成bit位除了首位全0,然后再变成bit位全1,再加1就会发生数据越位,所有bit位变成全0,然后再由bit全0–>bit位全1,构成了一个头尾相交的圆环。

但是和无符号数据类型不同的是:

  • 有符号的数它的二进制位比无符号的数少了一位数值位,并且我们规定1000…0000000表示的是最小的负数

但我们应注意:

  • 二进制数存储和表示无论是正数还是负数都是采用补码的方式,而只是因为我们把无符号数据看做正数,原码和补码一样,且多了一位数值位才导致了表示和存储方式看起来不同,实际都是一样用补码的形式进行存储和表示。
无符号和有符号数的异同详述
不同无符号数多了一位数值位
相同实际都是一样用补码的形式进行存储和表示
重要规定(有符号的数)1000…0000000表示的是最小的负数

以signed char为例:

10000000
11111111
00000000
01111111

等价于:

127
0
-128
-1

了解这些,我们就可以把上面的例子剖析
例子:

#include<stdio.h>
int main() {
	int a = 2147483647;
	int b = 1;
	printf("%d %u", a + b, a + b);
	return 0;
}

运行结果:
在这里插入图片描述

疑惑剖析
为什么用占位符%d打印的结果是负数?(1)十进制:2147483648–>二进制(补码):01111111111111111111111111111111;十进制:1–>二进制(补码):00000000000000000000000000000001;相加得:10000000000000000000000000000000(补码)(2)又用%d进行打印,%d是用来打印int类型数据的,所以我们要把相加得的结果转换为原码打印出来(这里要用重要规定)
为什么用占位符%u打印的结果是正数?(1)同上;(2)又用%u进行打印,%u是用来打印无符号整数的,无符号整数的特别之处——就在于我们是把它看作有符号整数中的正数,就导致:它的原码和反码是一样的,所以打印在屏幕上的数就是相加结果的十进制数
对于占位符的思考占位符给了我们一个理解和读取二进制数(补码)的视角方式

(3)整型提升
问题答案
什么叫整型提升?c语言的整型算术运算总是至少缺省(默认)整型类型的精度进行计算。为了获得这个精度,表达式中字符型(char)和短整型(short)在使用之前就被系统自动转换为普通整型(int),这种转换就叫整型提升
整型提升的意义是什么?表达式的整型运算要在CPU的加法器和其他运算器件中进行,而该运算器的操作数的字节长度就为int的字节长度
数据提升的条件和对象发生在小于整型类型的数据类型上

提升规则

对象
有符号数
正数
高位补0
无符号数
看补码
最高位为1则高位补1.否则补0
负数
高位补1

本质就是看补码的最高位是1还是0,是1补1,是0补0


(4)数据截断
问题答案
什么是数据截断?就是一个字节长度较小的数据类型在接收一个字节长度较大的数据类型时只会从字节长度较大的数据的数据低位开始接收,直至填满自己的所有二进制位
会有什么结果?可能会导致数据的丢失,一定会导致字节的减少

熟练掌握这些,我们就基本能预见和理解整型数据运算屏幕上打印的结果,下面就以一些例子来加深和巩固对以上知识的理解

例:

#include<stdio.h>
int main() {
	char a = 3;
	//00000011
	char b = 127;
	//01111111
	char c = a + b;
	//因a和b参加运算,所以要发生整型提升
	//整型提升规则:高位补符号位(在大部分编译器中,char等价于signed char,即有符号,最高位为符号位,范围为:-128~127;无符号的char类型数据范围为:0~255;
	//整型提升:
	//00000000000000000000000000000011
	//00000000000000000000000001111111
//结果00000000000000000000000010000000
	//截断(发生在高字节类型转化为低字节):
	//10000000              补码
	//10000011
	printf("%d", c);
	//打印结果为:-126
	return 0;
}
//也可以用圆环秒解:0 1 2 ~ 126 127 ~-1 -2 -3 ~ -127 -128 ~ 0 1 2 ~~
  • 注释的解析很全,不用再过多解释,对照上面的知识点进行理解

三、大小端介绍

1.来历

这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit位。但是在c语言中除了8bit的char之外,还有16bit位的short型,32位的long型(取决于具体编译器);另外,对于位数大于8位的处理器(16bit或32bit),由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排进内存中存储的问题。由此产生了大端和小端。


2.模式介绍及效果

模式(全称)效果
大端字节序存储数据的低位字节存放在高地址
小端字节序存储数据的低位字节存放在低地址

实际效果:

自己模拟
在这里插入图片描述


VS2022上的内存窗口
在这里插入图片描述


3.模式判断

我们可以借助一个2015年百度的笔试题观察大小端的区别

题目:写一个代码,实现大小端的判断

代码:

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

思路:

序号步骤
1用char*类型的指针一个一个字节地访问int类型变量a的各个字节
2我们可以把a赋值为只有第一个字节有值的整数,这里赋值为1
3前提:我们知道指针访问内存的习惯是从低地址到高地址
4如果*p == 1,说明低地址存放的字节是低位字节,也就是小端存储
5如果*p == 0,说明低地址存放的字节是高位字节,也就是大端存储

快乐的时光总是短暂,咱们下篇博文再见啦!!!不要忘了,给小编点点赞和收藏支持一下,在此非常感谢!!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++篇】红黑树的实现

目录 前言&#xff1a; 一&#xff0c;红黑树的概念 1.1&#xff0c;红黑树的规则 1.2&#xff0c;红黑树的最长路径 1.3&#xff0c;红黑树的效率分析 二&#xff0c;红黑树的实现 2.1&#xff0c;红黑树的结构 2.2&#xff0c;红黑树的插入 2.2.1&#xff0c;大致过程…

【MySQL】使用C语言链接

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;MySQL 目录 一&#xff1a;&#x1f525; MySQL connect &#x1f98b; Connector / C 使用&#x1f98b; mysql 接口介绍&#x1f98b; 完整代码样例 二&#xff1a;&#x1f525; 共勉 一&#…

音视频入门基础:RTP专题(4)——FFmpeg源码中,判断某文件是否为SDP文件的实现

一、引言 执行《音视频入门基础&#xff1a;RTP专题&#xff08;2&#xff09;——使用FFmpeg命令生成RTP流》中的“媒体文件转推RTP的FFmpeg命令”会生成一个SDP文件&#xff0c;该文件内容如下&#xff1a; v0 o- 0 0 IN IP4 127.0.0.1 sNo Name t0 0 atool:libavformat 61…

SSM项目简单的增删改查

目录 一、表 二、创建项目 1.创建mavenJavaWeb项目 2.补齐目录 3.导入依赖 三、创建包结构 四、实体类 五、spring框架 1.service接口和实现类 (1)service接口 (2)实现类 2.applicationContext.xml配置文件 六、spring整合springMVC 1.web.xml 2.spring-mvc.xml …

【Vim Masterclass 笔记13】第 7 章:Vim 核心操作之——文本对象与宏操作 + S07L28:Vim 文本对象

文章目录 Section 7&#xff1a;Text Objects and MacrosS07L28 Text Objects1 文本对象的含义2 操作文本对象的基本语法3 操作光标所在的整个单词4 删除光标所在的整个句子5 操作光标所在的整个段落6 删除光标所在的中括号内的文本7 删除光标所在的小括号内的文本8 操作尖括号…

el-table多级表头和列单元格合并

1、表格结构 <el-table:data"dialogForm.tableData"stripe:border"true":span-method"arraySpanMethod"><!-- 日期列 --><el-table-column prop"time" label"日期" align"center" /><!-- 重…

工程水印相机结合图纸,真实现场时间地点,如何使用水印相机,超简单方法只教一次!

在工程管理领域&#xff0c;精准记录现场信息至关重要。水印相机拍照功能&#xff0c;为工程人员提供了强大的现场信息记录工具&#xff0c;助力工程管理和统计工程量&#xff0c;更可以将图片分享到电脑、分享给同事&#xff0c;协同工作。 一、打开图纸 打开手机版CAD快速看图…

uniApp开通uniPush1.0个推,SpringBoot集成uniPush1.0个推

uniApp开通unipush1.0个推&#xff0c;SpringBoot程序集成 一、APP开通unipush1.0个推(商户App源码仅支持1.0个推) 1.app模块配置开通推送 2.应用开通推送 3.开通后点击消息推送菜单会看到如下页面 完成以上步骤后 此时android 仅支持在线推送。 4.配置各厂商离线推送 暂未…

升级 SpringBoot3 全项目讲解 — 为什么 SpringBoot3 应该抛弃 Maven,搭配 Gradle 来使用?

学会这款 &#x1f525;全新设计的 Java 脚手架 &#xff0c;从此面试不再怕&#xff01; 随着 Spring Boot 3 的发布&#xff0c;许多开发者开始考虑如何将现有项目升级到最新版本。Spring Boot 3 带来了许多新特性&#xff0c;包括对 Java 17 的支持、更好的性能优化以及对 G…

Yolov8 目标检测剪枝学习记录

最近在进行YOLOv8系列的轻量化&#xff0c;目前在网络结构方面的优化已经接近极限了&#xff0c;所以想要学习一下模型剪枝是否能够进一步优化模型的性能 这里主要参考了torch-pruning的基本使用&#xff0c;v8模型剪枝&#xff0c;Jetson nano部署剪枝YOLOv8 下面只是记录一个…

【深度学习】关键技术-激活函数(Activation Functions)

激活函数&#xff08;Activation Functions&#xff09; 激活函数是神经网络的重要组成部分&#xff0c;它的作用是将神经元的输入信号映射到输出信号&#xff0c;同时引入非线性特性&#xff0c;使神经网络能够处理复杂问题。以下是常见激活函数的种类、公式、图形特点及其应…

图数据库 | 18、高可用分布式设计(中)

上文我们聊了在设计高性能、高可用图数据库的时候&#xff0c;从单实例、单节点出发&#xff0c;一般有3种架构演进选项&#xff1a;主备高可用&#xff0c;今天我们具体讲讲分布式共识&#xff0c;以及大规模水平分布式。 主备高可用、分布式共识、大规模水平分布式&#xff…

Oracle 终止正在执行的SQL

目录 一. 背景二. 操作简介三. 投入数据四. 效果展示 一. 背景 项目中要求进行性能测试&#xff0c;需要向指定的表中投入几百万条数据。 在数据投入的过程中发现投入的数据不对&#xff0c;需要紧急停止SQL的执行。 二. 操作简介 &#x1f449;需要DBA权限&#x1f448; ⏹…

Datawhale组队学习笔记task1——leetcode面试题

文章目录 写在前面刷题流程刷题技巧 Day1题目1、0003.无重复字符的最长子串解答&#xff1a;2.00004 寻找两个正序数组的中位数解答&#xff1a;3.0005.最长回文子串解答4.0008.字符串转换整数解答&#xff1a; Day2题目1.0151.反转字符串中的单词解答2.0043.字符串相乘解答3.0…

K3二开:在工业老单工具栏增加按钮,实现打印锐浪报表

在上次实现用GridRepot报表实现打印任务单后&#xff0c;在想着能不能给将生产任务单原来要通过点击菜单栏&#xff0c;打印任务单的功能&#xff0c;在工具栏上也增加按钮实现&#xff0c;这样就不需要多点了。 原本是需要点击菜单栏才能实现的 现在在工具栏上增加按钮实现同…

[计算机网络]一. 计算机网络概论第一部分

作者申明&#xff1a;作者所有文章借助了各个渠道的图片视频以及资料&#xff0c;在此致谢。作者所有文章不用于盈利&#xff0c;只是用于个人学习。 1.0推荐动画 【网络】半小时看懂<计算机网络>_哔哩哔哩_bilibili 1.1计算机网络在信息时代的作用 在当今信息时代&…

机器学习之支持向量机SVM及测试

目录 1 支持向量机SVM1.1 概念1.2 基本概念1.3 主要特点1.4 优缺点1.5 核函数1.6 常用的核函数1.7 函数导入1.8 函数参数 2 实际测试2.1 二维可视化测试代码2.2 多维测试 1 支持向量机SVM 1.1 概念 支持向量机&#xff08;Support Vector Machine&#xff0c;简称SVM&#xff…

云服务信息安全管理体系认证,守护云端安全

在数据驱动的时代&#xff0c;云计算已成为企业业务的超级引擎&#xff0c;推动着企业飞速发展。然而&#xff0c;随着云计算的广泛应用&#xff0c;信息安全问题也日益凸显&#xff0c;如同暗流涌动下的礁石&#xff0c;时刻威胁着企业的航行安全。这时&#xff0c;云服务信息…

服务器数据恢复—Zfs文件系统数据恢复案例

服务器数据恢复环境&故障&#xff1a; 一台zfs文件系统的服务器&#xff0c;管理员误操作删除了服务器上的数据。 服务器数据恢复过程&#xff1a; 1、将故障服务器中所有硬盘做好标记后取出&#xff0c;硬件工程师检测后没有发现有硬盘存在硬件故障。以只读方式将所有硬盘…

​​​​​​​​​​​​​​★3.3 事件处理

★3.3.1 ※MouseArea Item <-- MouseArea 属性 acceptedButtons : Qt::MouseButtons containsMouse : bool 【书】只读属性。表明当前鼠标光标是否在MouseArea上&#xff0c;默认只有鼠标的一个按钮处于按下状态时才可以被检测到。 containsPress : bool curs…