重生之我在异世界学编程之C语言:数据在内存中的存储篇(上)

news2024/12/25 14:21:13

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

很高兴在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,说明低地址存放的字节是高位字节,也就是大端存储

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

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

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

相关文章

线程的概念及基本应用

目录 线程的概念 Java中多线程应用 继承Thread类 实现Runnable接口 实现Callable接口 线程的生命周期 线程的基本操作及原理 Thread.join的使用及原理 Thread.sleep的作用 问题 Thread.sleep的工作流程 wait和notify的使用 wait notify 例子 生产者消费者模式 Th…

联通软研院:基于OceanBase落地检索增强生成 (RAG) 的应用实践

本文作者&#xff1a;邱永刚&#xff0c;联通软件研究院OceanBase研发负责人&#xff0c;主要负责中国联通自研关系型数据库分布式CUDB研发、支撑、运维工作。 近年来&#xff0c;生成式人工智能技术取得了飞速进步&#xff0c;很多大模型在自然语言处理及对话系统领域的运用吸…

【更新】LLM Interview

课程链接&#xff1a;BV1o217YeELo 文章目录 LLM基础相关1. LLMs概述2. 大语言模型尺寸3. LLMs的优势与劣势4. 常见的大模型分类5. 目前主流的LLMs开源模型体系有哪些&#xff08;Prefix Decoder&#xff0c;Causal Decoder&#xff0c;Encoder-Decoder的区别是什么&#xff09…

模型 课题分离

系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。明确自我与他人责任。 1 课题分离的应用 1.1课题分离在心理治疗中的应用案例&#xff1a;李晓的故事 李晓&#xff0c;一位28岁的软件工程师&#xff0c;在北京打拼。他面临着工作、家庭和感情的多重…

sqlite 自定以脚本解释器

应用程序使用 libfdt 解析设备树,获取兼容性配置 内核源码支持libfdt 标准设备树语法,不用自己再创造 非常的爽,因为设备树支持预编译 一些可以跑类 BSD 系统的设备也可以使用这样的方法,不仅仅是在linux 系统上跑 有pylibfdt 支持解析设备树&#xff0c;校验设备树是否是正确的…

某医院vsan部署技术手册

环境配置 服务器4900G5五台 配置信息&#xff1a;cpu 8368*2颗 &#xff0c;内存256GB ,双口万兆网卡两个&#xff0c;四口千兆&#xff0c;RAID卡LSI9361-8i12G SAS RAID &#xff0c;两块固态盘480SSD &#xff0c;2*1.92TB NVME盘&#xff0c;5*8T盘。 万兆交换机两台H3C…

【编辑器扩展】打开持久化路径/缓存路径/DataPath/StreamingAssetsPath文件夹

代码 [MenuItem("Assets/Open Explorer/PersistentDataPath")]public static void OpenPersistentDataPath(){Application.OpenURL(Application.persistentDataPath);}[MenuItem("Assets/Open Explorer/DataPath")]public static void OpenDataPath(){Appl…

【day14】异常处理与Object类深入解析

【day13】回顾 在深入探讨异常处理与Object类之前&#xff0c;让我们回顾一下【day13】中的关键内容&#xff1a; 权限修饰符&#xff1a; public&#xff1a;最广的访问范围&#xff0c;任何地方都可以访问。protected&#xff1a;在同包和子类中可以访问。默认&#xff08;无…

【NLP 17、NLP的基础——分词】

我始终相信&#xff0c;世间所有的安排都有它的道理&#xff1b;失之东隅&#xff0c;收之桑榆 —— 24.12.20 一、中文分词的介绍 1.为什么讲分词&#xff1f; ① 分词是一个被长期研究的任务&#xff0c;通过了解分词算法的发展&#xff0c;可以看到NLP的研究历程 ② 分词…

11.vector的介绍及模拟实现

1.vector的介绍 记得之前我们用C语言实现过顺序表&#xff0c;vector本质上也是顺序表&#xff0c;一个能够动态增长的数组。 vector 的底层实现机制 - 动态数组&#xff1a;vector 的底层实现是动态数组。它在内存中连续存储元素&#xff0c;就像一个可以自动调整大小的数…

# 起步专用 - 哔哩哔哩全模块超还原设计!(内含接口文档、数据库设计)

↑ 上方下载文档 (大小374KB) 接口文档预览 (超过50个接口) 一、数据库25张表er-关系清晰构图&#xff01;(tip: 鼠标右键图片 > 放大图像) 二、难点/经验 详细说明 热门评论排序评论点赞列表|DTO封装经验分享|精华接口文档说明 组员都说喜欢分档对应枚举码 如果这篇文章…

android RecyclerView 垂直显示示例(java)

RecyclerView垂直列表显示示例&#xff0c;显示图片加文字。 1、RecyclerView.Adapter适配器 public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ViewHolder> {private Context mContext;private List<TitleBean> titleBeans;public ListAdapt…

华为云语音交互SIS的使用案例(文字转语音-详细教程)

文章目录 题记一 、语音交互服务&#xff08;Speech Interaction Service&#xff0c;简称SIS&#xff09;二、功能介绍1、实时语音识别2、一句话识别3、录音文件识别4、语音合成 三、约束与限制四、使用1、API2、SDK 五、项目集成1、引入pom依赖2、初始化 Client1&#xff09;…

GitCode 光引计划投稿|智能制造一体化低代码平台 Skyeye云

随着智能制造行业的快速发展&#xff0c;企业对全面、高效的管理解决方案的需求日益迫切。然而&#xff0c;传统的开发模式往往依赖于特定的硬件平台&#xff0c;且开发过程繁琐、成本高。为了打破这一瓶颈&#xff0c;Skyeye云应运而生&#xff0c;它采用先进的低代码开发模式…

网络刷卡器的功能和使用场景

网络刷卡器是一种连接互联网的设备&#xff0c;能够通过网络将读取到的各种卡片信息传输至服务器进行处理。这类刷卡器通常支持多种类型的卡片&#xff0c;如银行卡、身份证、会员卡、公交卡等&#xff0c;并运用现代信息技术确保数据的安全性和高效性&#xff0c;功能十分强大…

从零开始C++游戏开发之第七篇:游戏状态机与回合管理

在游戏开发的道路上&#xff0c;状态管理是一个无法绕开的重要课题。尤其是在棋牌类游戏中&#xff0c;游戏的进行需要有条不紊地按照回合推进&#xff0c;同时管理多个游戏状态&#xff0c;如“等待玩家加入”、“游戏进行中”、“结算阶段”等。如何优雅且高效地实现这些逻辑…

有没有检测吸烟的软件 ai视频检测分析厂区抽烟报警#Python

在现代厂区管理中&#xff0c;安全与规范是重中之重&#xff0c;而吸烟行为的管控则是其中关键一环。传统的禁烟管理方式往往依赖人工巡逻&#xff0c;效率低且存在监管死角&#xff0c;难以满足当下复杂多变的厂区环境需求。此时&#xff0c;AI视频检测技术应运而生&#xff0…

CentOS7网络配置,解决不能联网、ping不通外网、主机的问题

1. 重置 关闭Centos系统 编辑->虚拟网络编辑器 还原默认设置 2. 记录基本信息 查看网关地址,并记录在小本本上 查看网段,记录下 3. 修改网卡配置 启动Centos系统 非root用户,切换root su root查看Mac地址 ifconfig 或 ip addr记录下来 修改配置文件 vim /et…

32岁前端干了8年,是继续做前端开发,还是转其它工作

前端发展有瓶颈&#xff0c;变来变去都是那一套&#xff0c;只是换了框架换了环境。换了框架后又得去学习&#xff0c;虽然很快上手&#xff0c;但是那些刚毕业的也很快上手了&#xff0c;入门门槛越来越低&#xff0c;想转行或继续卷&#xff0c;该如何破圈 这是一位网友的自述…

麒麟操作系统服务架构保姆级教程(三)ssh远程连接

如果你想拥有你从未拥有过的东西&#xff0c;那么你必须去做你从未做过的事情 作为一名成熟运维架构师&#xff0c;我们需要管理的服务器会达到几十台&#xff0c;上百台&#xff0c;上千台&#xff0c;甚至是上万台服务器&#xff0c;而且咱们的服务器还不一定都在一个机房&am…