C语言学习分享(第九次)------数据的存储

news2024/11/17 14:26:44

💓博主CSDN主页:杭电码农-NEO💓

⏩专栏分类:C语言学习分享⏪

🚚代码仓库:NEO的学习日记🚚

🌹关注我🫵带你学习更多C语言知识
  🔝🔝


在这里插入图片描述


数据的存储

  • 1. 前言🚩
  • 2. 整型在内存中的存储🚩
    • 2.1 源码,反码,补码🏁
  • 3. 大端和小端🚩
    • 3.1 为什么有大端小端?🏁
    • 3.2 怎样判断大小端🏁
  • 4. 类型的范围🚩
    • 4.1 char 类型的范围🏁
  • 5. 练习🚩
    • 5.1 练习一🏁
    • 5.2 练习二🏁
    • 5.3 练习三🏁
    • 5.4 练习四🏁
    • 5.5 练习五🏁
  • 6. 总结🚩


1. 前言🚩

本篇文章带给大家的内容有,整型在内存中的存储,大端小端的介绍与判断,和一些练习.从这篇文章开始,我们将进入C语言进阶知识的部分.


2. 整型在内存中的存储🚩

比如我们定义两个整型变量:

int a = 20;
int b = -10;

我们知道整型在内存中占四个字节的空间,在这之前我们先了解下面的概念


2.1 源码,反码,补码🏁

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

  • 源码:直接将数值按照正负数的形式翻译成二进制就可以得到原码。
  • 反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。
  • 补码:反码+1就得到补码。

我们说正整数的源码,反码,补码都相同.并且对于整形来说:数据存放内存中其实存放的是补码。

这是因为在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;
同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。

	int main()
{
	int num  = 20;//创建一个整型变量,叫 num,这时num向内存申请4个字节来存放数据
	//4个字节-32比特位
	//00000000000000000000000000010100-原码
	//00000000000000000000000000010100-反码
	//00000000000000000000000000010100-补码
    //正整数源反补相同
	int num2 = -10;//
	//10000000000000000000000000001010 - 原码
	//11111111111111111111111111110101 - 反码
	//11111111111111111111111111110110 - 补码
	//
	return 0;
}

假设我们要将这两个数相加,我们试试用反码,和补码相加,哪个是正确的:

源码相加:

//0000000000000000000000010100  num
//1000000000000000000000001010  num2
//1000000000000000000000011110  30的源码

补码相加:

//000000000000000000000010100  num
//111111111111111111111110110  num2
//011111111111111111111110110  补码
//000000000000000000000001010  10的源码   

我们有看见用补码做加减法是刚好符合逻辑的.

我们再来看看 -10 在 vs2022 编译器上的内存存储:

在这里插入图片描述

这里是倒着存放的数据,后面会讨论,现在我们暂且不看,但是我们能感受到实际上数据在内存中的存储是以补码的形式存储的


3. 大端和小端🚩

我们之前观察了补码在内存中的存储,我们发现有一点奇怪,为什么数据是倒着放的?这里我们用变量a来阐述这个问题

int a = 0x11223344;

我们说内存分为高地址和低地址,而数据又分高位和低位,比如说这里 11223344 的44 就是数据的低位,而 11 就是数据的高位,下面我给出大小端的定义:

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

字节序—就是以字节为单位,讨论存储顺序的.这里的 11 为一个字节, 22 为一个字节,整型共四个字节


在这里插入图片描述


3.1 为什么有大端小端?🏁

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

例如:一个 16bit 的 short 型 x ,在内存中的地址为 0x0010 , x 的值为 0x1122 ,那么 0x11 为高字节, 0x22 为低字节。对于大端模式,就将 0x11 放在低地址中,即 0x0010 中, 0x22 放在高地址中,即 0x0011 中。小端模式,刚好相反。我们常用的 X86 结构是小端模式,而 KEIL C51 则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。


3.2 怎样判断大小端🏁

怎么写一个代码判断当前机器是大端还是小端? 这里我们定义一个整型变量a的值为1

它在大小端机器上应该是这样存储的:

在这里插入图片描述


我们想到,int类型的指针解引用可以访问四个字节的空间,而char类型的指针解引用可以访问一个字节的空间,我们定义一个char类型的指针指向变量a,如果对指针解引用的结果是1,那么当前机器就是小端,解引用后结果是0那么机器就是大端.

#include<stdio.h>
	int main()
{
		int a = 1;
		char* p = (char*)&a;//强制类型转换,否则会报警告
		if (*p == 1)
		{
			printf("当前机器为小端");
		}
		else
		{
			printf("当前机器为大端");
		}
	return 0;
}

4. 类型的范围🚩

我们把整型家族划分为:
在这里插入图片描述
下面我们主要来讨论 char 类型的范围,并做一些练习


4.1 char 类型的范围🏁

我们知道char类型在内存中占1个字节,也就是八个比特位(也可以说占八个二进制位),我们来讨论一下有符号char和无符号char的数据存储范围.

在这里插入图片描述
再来看看无符号位的存储:

在这里插入图片描述

  • 有符号位char的范围: -128~127
  • 无符号位char的范围: 0~255

并且我们可以发现一个规律,无符号char中,255+1,又跳到0去了,形成了一个循环,所以我们可以画这样一个圆形的循环图来理解:

在这里插入图片描述

在这里插入图片描述

我们可以看见,无符号位的char的127+1变成了128,而有符号位的char中的127+1变成了-128.并且无符号位中的255加1又回到了0,所以无符号char能存储的最大数就是255.超过255又会重新回到0.


5. 练习🚩

5.1 练习一🏁

1.
//输出什么?
#include <stdio.h>
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;
}

这里a和b很好判断,在vs编译器下,如果没有指定是否是有符号或者无符号,就默认为有符号形,然而c是无符号char类型的变量,它存储-1的补码在内存中,-1的补码是 11111111 然而无符号数的源反补码都相同,所以当-1被存储在无符号数中后,11111111八个1都不是符号位,值就为255了.


5.2 练习二🏁

2.
#include <stdio.h>
int main()
{
    char a = -128;
    printf("%u\n",a);
    return 0;
}

首先这里会输出4294967168,为什么呢?首先a是有符号char类型的变量,存储-128的值,然而%u是打印无符号整数的意思,所以这里的char类型会发生整型提升,从一个字节提升至4个字节,又因为a是负数,它的的符号位为1,所以整型提升时前面全部都是补的1,所以我们就得到了一个数的补码,然而无符号数的源反补码都相同,所以我们就会得到一个特别大的数的源码.


5.3 练习三🏁

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

这里会死循环打印,我们来分析分析,这里的变量 i 是无符号整型,一个无符号数是肯定不会是负数的,当 i 等于0时再减去1,它会像我们刚刚讨论的无符号char类型一样变成无符号整型中的最大值,而不是-1,所以它会一直打印下去

这里给大家看一看现象:

死循环


5.4 练习四🏁

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

这里数组a的长度为255,我们来分析这一点.首先,数组a中存储的数据是有符号char类型的数据,数据范围是: -128 ~ 127之间.这里循环中 i 的范围是: -1 ~ -999 之间,数组中的内容会从-1开始一直往后存储,当i等于-128时,-1-128这时根据我们上面画的循环图,-1-128就等于127.下一步-1-129同理也就是等于126,然后125,124…这样存储下去,直到它变为0后又减一变成-1,以此循环往复直到装满1000个数为止.

当我们分析到这里还没有结束,我们知道这1000个元素其实就是 -128~127之间所有的数重复了几遍组成的,然而我们知道 strlen操作符的结束标志是遇见’\0’, 并且’\0’的ASCLL值是0,也就是说当strlen遇见0时,它就会终止,在外面数组中遇见的第一个0就会被系统当作数组的长度,根据外面刚才的分析,可以得出,第一个0出现时有128+127=255个元素已经在数组中,所以系统会认为数组的长度为255.也就是打印255.


5.5 练习五🏁

5.
#include <stdio.h>
unsigned char i = 0;
int main()
{
    for(i = 0;i<=255;i++)
   {
        printf("hello world\n");
   }
    return 0;
}

这个代码也会死循环打印hello world,这是因为当循环走到 i 等于255时, i 再加一其实不是256,因为无符号char类型能够存储的最大数就是255,根据外面刚刚画的循环图,255加一后就会重新走到0,以此一直循环下去.


6. 总结🚩

在数据的存储中,还有一个比较重要的点是浮点型在内存中的存储,这个部分放在下一章节讲解.

🔎 下期预告: C语言进阶 🔍
\

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

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

相关文章

符合国情的supabase私有化部署(0)

符合国情的supabase私有化部署(0) 符合国情的supabase私有化部署(0) 前言开源 BaaS 解决方案快速开始 获取部署文件服务明细 容器启动后创建一个前端app注册邮箱SMTP协议jwt token和kong网关配置并应用更改数据库密码k8s 部署参考尾言常见问题 name resolution failedInvalid …

Python:Python编程:从入门到实践__超清版:Python标准库

Python标准库 1. OrderedDict2. threading三级目录 Python标准库是一组模块&#xff0c;按照的Python都包含了它&#xff0c;我们只需要在程序开头包含一条简单的 import 语句&#xff0c;就可以使用标准库中的任何函数和类。 下面我介绍几个重点 标准库 os : 提供一些与操作系…

Word控件Aspose.Words教程:使用 Java 处理 SXC 和 FODS 文件

Aspose.Words是一种高级Word文档处理API&#xff0c;用于执行各种文档管理和操作任务。API支持生成&#xff0c;修改&#xff0c;转换&#xff0c;呈现和打印文档&#xff0c;而无需在跨平台应用程序中直接使用Microsoft Word。 Aspose API支持流行文件格式处理&#xff0c;并…

NUC980编译错误,multiple target patterns(多个目标匹配)

1&#xff1a;问题&#xff1a; 昨天环境编译的还是没问题的&#xff0c;今天就出错了 &#xff1a; Makefile:133: *** multiple target patterns. Stop 此时&#xff1a;make make clean make disclean 都不可以使用了&#xff0c;报一样的错误。 2&#xff1a;解决办法&…

二叉搜索树的操作、模拟实现、应用以及性能的介绍

一、二叉搜索树 1. 性质 &#xff08;1&#xff09;如果左子树不是空&#xff0c;那么左子树上的所有节点的值都小于根节点的值 &#xff08;2&#xff09;如果右子树不是空&#xff0c;那么右子树上的所有节点的值都大于根节点的值 &#xff08;3&#xff09;左右子树也分别为…

Redis的网络模型

计算机硬件包括CPU&#xff0c;内存&#xff0c;网卡 为了避免用户应用和操作系统内核产生冲突乃至内核崩溃&#xff0c;用户应用和内核是隔离开的 1)进程的寻址空间会被划分成两部分&#xff0c;内核空间和用户空间&#xff0c;内核和用户应用都无法直接访问物理内存&#xff…

【Linux】在Ubuntu上部署web项目(Ubuntu版本为16.04.7,jdk1.8、mysql5.7、tomcat9.0.48)

介绍 这里是小编成长之路的历程&#xff0c;也是小编的学习之路。希望和各位大佬们一起成长&#xff01; 以下为小编最喜欢的两句话&#xff1a; 要有最朴素的生活和最遥远的梦想&#xff0c;即使明天天寒地冻&#xff0c;山高水远&#xff0c;路远马亡。 一个人为什么要努力&a…

河道水位监测:河道水位监测用什么设备

中国地形复杂&#xff0c;气候多样&#xff0c;导致水资源分布不均&#xff0c;洪涝和干旱等问题时有发生。同时&#xff0c;人类活动也对水资源造成了很大压力&#xff0c;工业和农业用水增加&#xff0c;河道水位下降&#xff0c;生态环境受到威胁。因此&#xff0c;对河道水…

【面向对象三大特性之继承】

目录 1.什么是继承2.父类成员访问2.1 子类访问父类的成员变量2.1.1 子类和父类不存在同名成员变量2.1.2 子类和父类存在同名成员变量 2.2子类中访问父类的成员方法2.2.1. 成员方法名字不同2.2.22. 成员方法名字相同 3.super关键字4.子类构造方法5.super和this的异同点6.代码块的…

可视化探索开源项目的 contributor 关系

引语&#xff1a;作为国内外最大的代码托管平台&#xff0c;根据最新的 GitHub 数据&#xff0c;它拥有超 372,000,000 个仓库&#xff0c;其中有 28,000,000 是公开仓。分布式图数据库 NebulaGraph 便是其中之一&#xff0c;同其他开源项目一样&#xff0c;NebulaGrpah 也有自…

用arcgis for javascript 开发一个三维地图(入门案例)

效果如图&#xff1a; 详细的步骤就不啰嗦介绍了&#xff0c;大家可以参考上一篇文章二维地图入门案例&#xff0c;这里只是改了一点引用和属性而已。 核心代码&#xff1a; SceneView 用于创建三维地图 require([“esri/Map”, “esri/views/SceneView”] 这里提一句有两种…

vue项目中的环境变量的应用

vue项目中的环境变量的应用 在Vue项目中使用环境变量可以方便地在开发、测试、生产等不同环境中进行配置&#xff0c;而无需修改代码。 项目根目录下创建一个.env文件或者.env.[mode]文件&#xff0c;其中mode表示开发、测试、生产等不同的环境&#xff0c;文件名的后缀部分指…

Python的分布式网络爬虫

分布式爬虫其实就是指利用多台计算机分布式地从互联网上采集数据的一种爬虫。它可以把大规模的任务分解成若干小规模的&#xff0c;由多台计算机并行进行处理&#xff0c;大大提高了效率和速度。 分布式爬虫有很多优势&#xff1a;解决单机爬虫效率低的问题&#xff0c;分布式…

【UR3系统升级到CB3.12附带URcap1.05】

【UR3系统升级到CB3.12附带URcap1.05】 1. 前言1.1 Polyscope 3.12更新须知1.2 更新步骤 2. 对 PSU 电压进行控制的步骤2.1 启动机器人电源2.2 启动机器人程序2.3 查看PSU 电压 3. Polyscope 3.12 软件下载3.1 CB 系列机器人3.2 下载软件包URUP 4. CB3 软件安装的指导4.1 连接示…

Kohl‘s百货的EDI需求详解

Kohls是一家美国的连锁百货公司&#xff0c;成立于1962年&#xff0c;总部位于美国威斯康星州的门多西。该公司经营各种商品&#xff0c;包括服装、鞋子、家居用品、电子产品、化妆品等&#xff0c;并拥有超过1,100家门店&#xff0c;分布在美国各地。本文将为大家介绍Kohls的E…

SDK接口远程调试【内网穿透】

文章目录 1.测试环境2.本地配置3. 内网穿透3.1 下载安装cpolar内网穿透3.2 创建隧道 4. 测试公网访问5. 配置固定二级子域名5.1 保留一个二级子域名5.2 配置二级子域名 6. 使用固定二级子域名进行访问 转发自cpolar内网穿透的文章&#xff1a;Java支付宝沙箱环境支付&#xff0…

stable diffusion使用入门

目录 1、stable diffusion简要说明 2、安装stable-diffusion-webui &#xff08;1&#xff09;下载地址 &#xff08;2&#xff09;执行启动命令 3、Lora模型介绍 4、模型下载 &#xff08;1&#xff09;Lora模型使用 &#xff08;2&#xff09;底座模型使用 1、stable…

初识开源接口测试工具——Postcat

Postcat 是一个强大的开源、跨平台&#xff08;Windows、Mac、Linux、Browsers...&#xff09;的 API 开发测试工具&#xff0c;支持 REST、Websocket 等协议&#xff08;即将支持 GraphQL、gRPC、TCP、UDP&#xff09;&#xff0c;帮助你加速完成 API 开发和测试工作。 它适合…

OLAP和OLTP

1&#xff1a;OLAP和OLTP对比 数据库系统可以在广义上分为联机事务处理&#xff08;Online Transaction Process&#xff0c;OLTP&#xff09;和联机分析处理&#xff08;Online Analyze Process&#xff0c;OLAP&#xff09;两种面向不同领域的数据库&#xff0c;OLAP数据库也…

vue-cli的使用

什么是单页面应用程序? ​ 单页面应用程序(Single Page Application)简称SPA。指的是一个web网站中只有唯一的一个html页面,所有的功能与交互都在这个唯一的页面内完成。 什么是vue-cli? ​ vue-cli是Vue.js开发的标准工具。它简化了基于webpack创建工程化的vue项目过程。…