手把手教你C语言‘数据的存储‘[doge]

2023-11-23 16:00

本文主要是介绍手把手教你C语言‘数据的存储‘[doge],希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

@[toc](目录)

想来学完大多语法后,大家都对整型,浮点型,字符型都有了大概的认识,简而言之,大概知道是什么.

对其相关的了解想要更进一步,那就必须要知道这些类型在内存中是如何存储的了.

彳亍,那我们接下来就浅谈这几种类型的存储.

目录

数据类型

整型,浮点型的存储

大小端讲解

例题巩固


数据类型

想想到现在我们学了什么?               好像啥也没学

那从最基本的类型说起,下面是我们学过的几种类型

short   2
int     4
long    4
long long    8float   4
double  8char   1

他们的类型决定了我们看待内存的视角,也就是我们怎么看它,像一个标签一样

而要讨论他们在内存中的存在方式,肯定要讨论它的大小了

大小(所占字节数)决定了他们的精度,也决定了取值的范围

自然类型的意义就出来了:

1.类型决定了看待内存的角度

说人话:计算机怎么看它的,我们又是怎么看它的

2.类型决定了他们的使用范围

简单点:一个桶子只能装1L的水,你装1.1L就会溢出

下面我们就具体分一下类

Q:啥?上面不是分了?

A:那只是概述

具体分类如下

整型:char:   (别急后面解释为啥放这)unsigned char
signed charshort:
unsigned short
signed shortint:
unsigned int
signed intlong:
unsigned long
signed longlong long :
unsigned long long
signed long long

char字符型放在‘整型家族’的原因是char存的不是字符,而是字符的ASCII值,是个数字

浮点型:float
double构造类型:数组,struct,enum,union  (注意是数组和结构体,后面的枚举和联合知道有它就行了)指针:
char*
int*
float*
double*
void*    等等等等
指针类型太多在这不一一列举了空类型:
void
函数返回值,函数参数,指针类一般都可以见到它

现在你应该明白数据的分类了.

那么归好类,就得讲讲这个东西是怎么存的了

整型和浮点型的数据存储方式不同

所以小白时期明明感觉没错,但是打印的结果很奇怪,有一部分就是这个问题没有解决

先说整型:

整型在内存里存的是补码

我们进行的加减乘除全是操作补码

计算机里表示一个数有三种方法--原码,反码,补码

原码--符号位+二进制序列

第一位是符号位  0代表正,1代表负

例:

5的二进制101,如果放进int里面,int是32位

那么就写成

正数的原反补三码相同,写出原码就等价于写出补码

负数复杂一点

反码==原码符号位不动,其余位按位取反

解释:第一位不动,其余位0变成1,1变成0

补码==反码+1

例:

这就是整型,long,longlong之类的都可以类推

值得一提的是char类型,一个字节,八位,所以取值范围:-128-127

下面推导char的类型(有符号的char)


1000 0001是几?

由计算机算出来是127,加上符号位的1表示负数,所以是-127

那最后11111111是几?

显然是-1,可以自己动笔推算一下

由以上就可以知道char类型的取值是一个循环

假若我们从0开始

那就是0  ->  127  ->  (-128)  ->  (-1)  ->  0

这是有符号的char的范围:-128-127

注:127+1==-128

127是百尺竿头,再进一步就是-128

同理也可知道无符号的char: 0 - 255

到这里,我们就知道了整型在内存种的存储方式,存的是补码,我们也要知道怎么表示他们

同时也推导了char的取值范围,整型到这就告一段落了

---------------------------

整型,浮点型的存储

下面我们谈谈浮点型:

来一道典型的例题看看:

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

猜猜这四个打印的值是多少?

想好了没?

公布答案:

小朋友是不是有很多的问号?

哈哈哈哈哈哈,说回正题

具体介绍下浮点型咋存的,再来解释打印的结果

float

记住这么几个数字  :1-8-23

double   

记住这么几个数字:  1-11-52

这几个数字意义是什么:

从前往后:符号位 -指数- 有效数字(S-E-M)

E是一个无符号数,后面解释为什么

例:

S:0表示正数,1表示负数(这点和整型对应上了)

E有八位,第八位是符号位吗?前面说过转换过程+127所以一定是正数,

所以E的第八位不是符号位,这是一个无符号数

上面是E不全为0或者不全为1

那如果E(指数)是全0或者全1呢,属于特殊情况,分类讨论

全0:说明这个数很小,想想+127都是0了,那读取的时候应用规则:E取1-127的值或者1-1023的值

全1:这个数的绝对值很大,趋于无穷(指数不能决定正负)

到此我们知道了浮点数的存储方式

十进制的浮点数->写成二进制->转换成指数形式->根据规则确定存入的S-E-M的值,再按规则取出来

这就是浮点数的存储

那么我们来解释一下最开始的例题:

不用往上翻了

从内存入手:

先看这四句话:

n以%d(整型的方式读取)打印肯定是9,没问题

float*和int*都操作四个字节,都可以拿到32位,不存在截取的问题

所以%f就是以浮点数的读取方式读取整型,由补码入手:

E全是0,无限接近0的一个数,float默认打印小数点后6位,

自然结果:

 

那再看后面两行:

第一行赋值为9.0,float型指针,以浮点数的方式存进去

那就有:

以%d的形式打印,也就是以整型的办法去读取:

正数,所以直接补码==原码

读取的十进制数也就是计算器所呈现的1091567616

以%f,也就是浮点型的方式去读取它,自然是9.000000

我们再比对一下结果:

ohhhhhhhh,一样的对吧.

------------------

到这里我们就知道了浮点数的存储方式,进度条过半

-----------------

大小端讲解

接下来就是大小端的问题了

先给定义:

大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;
小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位 , ,保存在内存的高地址中。
简单点,说话的方式简单点
数字有高位和低位
例:12345  5是个位,是低位
10101010   0是2^0  是低位
地址有高地址和低地址
例:0x00000001  低地址
0x00000005  高地址
知道这两个再理解大小端:
大端:数据的低位 放在  高地址   
小端:数据的低位 放在 低地址
这么说还是太抽象了,举例说明:
这是VS编译器,通过调试我们知道a里面存的是这玩意?
所以VS是大端还是小端?
前情提要:
'0x'告诉编译器这是个十六进制数字,由于32个二进制位显示过长,所以调试显示的是16进制.
一个十六进制位==4个二进制位
两个十六进制位==1个字节,所以上面显示的一组数字就是一个字节,四组四个字节,满足int的大小.
由上图可知:低位放到了低地址,高位放到了高地址,对应定义,确实是小端存储.
对大小端有了一个认识后,我们来看一道题:
请简述大端字节序和小端字节序的概念,设计一个小程序来判断当前机器的字节序。( 10 分)
大端字节序:高字节内容保存在内存的低地址处,低字节内容保存在内存的高地址处
小端字节序: (看啥?补充啊,上面给了你个范本了)
小程序:
以1为例(数字简单好推算结果)
1==0x00 00 00 01
若是大端字节序,存的就是:00 00 00 01(正着存)
若是小端字节序,存的就是:01 00 00 00(倒着存)
显然只要看第一个字节的内容是1还是0?-> 操作一个字节-> char类型的指针 ->用拿到的数去 '&1' 就可以知道拿到的数是不是1
代码如下:
int check(int a)
{char* tmp = (char*)&a;if (*tmp & 1 == 1){return 1;}return 0;
}int main()
{int a = 1;if (check(a)){printf("小端\n");}else{printf("大端\n");}

再次证明VS是小端字节序机器.
------------------进度过去3/4,就快结束了
对于基础知识我们有了一定的了解,下面就是做题巩固了

例题巩固

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

因为是第一题,讲详细一点

某些编译器默认char是有符号的signed char,有些又当作unsigned char处理。VS默认signed char

char a==signed char a (VS编译器下)

有符号的char:

我们再来看看结果:
没问题!
有个诀窍:char--  在-128-127这个范围里面的肯定就是这个数本身
unsigned char   ---  0-255  在这个范围里面的肯定就是这个数本身,此题-1不在那就加或减256,让它进入这个范围(-1+256==255)

2.

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

-128在这个范围内,但是注意是无符号数打印(%d打印那就是-128),所以还是从补码入手

让我们来比对下答案:
没问题
3.最后一题
int i= -20;
unsigned  int  j = 10;
printf("%d\n", i+j); 
//按照补码的形式进行运算,最后格式化成为有符号整数

可以,没问题!

------------------终于写完了!-------------

能看到这真的强:

----------------------------

感谢阅读,如果有帮助别忘了点赞,这对我帮助很大,下次再见!

这篇关于手把手教你C语言‘数据的存储‘[doge]的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/419082

相关文章

C语言小项目实战之通讯录功能

《C语言小项目实战之通讯录功能》:本文主要介绍如何设计和实现一个简单的通讯录管理系统,包括联系人信息的存储、增加、删除、查找、修改和排序等功能,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录功能介绍:添加联系人模块显示联系人模块删除联系人模块查找联系人模块修改联系人模块排序联系人模块源代码如下

Java中注解与元数据示例详解

《Java中注解与元数据示例详解》Java注解和元数据是编程中重要的概念,用于描述程序元素的属性和用途,:本文主要介绍Java中注解与元数据的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参... 目录一、引言二、元数据的概念2.1 定义2.2 作用三、Java 注解的基础3.1 注解的定义3.2 内

将sqlserver数据迁移到mysql的详细步骤记录

《将sqlserver数据迁移到mysql的详细步骤记录》:本文主要介绍将SQLServer数据迁移到MySQL的步骤,包括导出数据、转换数据格式和导入数据,通过示例和工具说明,帮助大家顺利完成... 目录前言一、导出SQL Server 数据二、转换数据格式为mysql兼容格式三、导入数据到MySQL数据

C++中使用vector存储并遍历数据的基本步骤

《C++中使用vector存储并遍历数据的基本步骤》C++标准模板库(STL)提供了多种容器类型,包括顺序容器、关联容器、无序关联容器和容器适配器,每种容器都有其特定的用途和特性,:本文主要介绍C... 目录(1)容器及简要描述‌php顺序容器‌‌关联容器‌‌无序关联容器‌(基于哈希表):‌容器适配器‌:(

C#提取PDF表单数据的实现流程

《C#提取PDF表单数据的实现流程》PDF表单是一种常见的数据收集工具,广泛应用于调查问卷、业务合同等场景,凭借出色的跨平台兼容性和标准化特点,PDF表单在各行各业中得到了广泛应用,本文将探讨如何使用... 目录引言使用工具C# 提取多个PDF表单域的数据C# 提取特定PDF表单域的数据引言PDF表单是一

基于Go语言实现一个压测工具

《基于Go语言实现一个压测工具》这篇文章主要为大家详细介绍了基于Go语言实现一个简单的压测工具,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录整体架构通用数据处理模块Http请求响应数据处理Curl参数解析处理客户端模块Http客户端处理Grpc客户端处理Websocket客户端

一文详解Python中数据清洗与处理的常用方法

《一文详解Python中数据清洗与处理的常用方法》在数据处理与分析过程中,缺失值、重复值、异常值等问题是常见的挑战,本文总结了多种数据清洗与处理方法,文中的示例代码简洁易懂,有需要的小伙伴可以参考下... 目录缺失值处理重复值处理异常值处理数据类型转换文本清洗数据分组统计数据分箱数据标准化在数据处理与分析过

大数据小内存排序问题如何巧妙解决

《大数据小内存排序问题如何巧妙解决》文章介绍了大数据小内存排序的三种方法:数据库排序、分治法和位图法,数据库排序简单但速度慢,对设备要求高;分治法高效但实现复杂;位图法可读性差,但存储空间受限... 目录三种方法:方法概要数据库排序(http://www.chinasem.cn对数据库设备要求较高)分治法(常

Python将大量遥感数据的值缩放指定倍数的方法(推荐)

《Python将大量遥感数据的值缩放指定倍数的方法(推荐)》本文介绍基于Python中的gdal模块,批量读取大量多波段遥感影像文件,分别对各波段数据加以数值处理,并将所得处理后数据保存为新的遥感影像... 本文介绍基于python中的gdal模块,批量读取大量多波段遥感影像文件,分别对各波段数据加以数值处

使用MongoDB进行数据存储的操作流程

《使用MongoDB进行数据存储的操作流程》在现代应用开发中,数据存储是一个至关重要的部分,随着数据量的增大和复杂性的增加,传统的关系型数据库有时难以应对高并发和大数据量的处理需求,MongoDB作为... 目录什么是MongoDB?MongoDB的优势使用MongoDB进行数据存储1. 安装MongoDB