C语言--数据的存储1

news2024/11/28 8:51:10

目录

  • 数据类型的介绍
    • 类型的意义
  • 类型的基本归类
    • 整形家族
    • 浮点型家族
    • 构造类型--自定义类型
    • 指针类型
    • 空类型
  • 整形在内存中的存储
  • 大小端
    • 大小端如何区分
    • 为什么会有大小端
    • 判断机器字节序

从本章开始,我们将正式进入C语言的进阶学习中。
本篇内容我们将学习 数据的存储

数据类型的介绍

在以往的学习当中,我们已经接触过许多的基本数据类型了,如下:

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

那么C语言中有没有字符串类型呢?
其实在C语言的环境中是没有的,很多高级语言java #c就有字符串类型,有string来表示字符串,用法和int很类似,但在C语言中字符串是通过字符指针来间接实现的。

类型的意义

我们使用这个类型可以开辟不同大小的空间(大小决定了使用范围)(例如int类型就会开辟4个字节大小的空间),同时也为程序员提供了一个观察内存空间的视角

类型的基本归类

整形家族

char
    unsigned char
    signed char
short
    unsigned short [int]
    signed short [int]
int
    unsigned int
    signed int
long
    unsigned long [int]
    signed long [int]

我们发现,char类型也被归在了整形家族中,这是因为在存储字符的时候,实际上是储存的ascll码值,而ascll码值实际上也是一串数字,所以char类型实际上也隶属于整形家族。

浮点型家族

double
float

构造类型–自定义类型

//结构体类型
//数组类型
//枚举类型
//联合体

指针类型

int* pi;
char* pc;
float* pf;
double* pb;

空类型

void

void 表示空类型
空类型的作用在于:
1,可作为函数的返回类型: void test ()
2,可作为函数的参数: void test ();
3,指针: void* p;

整形在内存中的存储

我们之前讲过一个变量的创建是要在内存中开辟空间的。空间的大小是根据不同的类型而决定的。
那接下来我们谈谈数据在所开辟内存中到底是如何存储的
举个例子:

int main()
{
	int a = -10;
	return 0;
}

图1

我们知道数据在内存中以2进制的形式存储。
而对于整数来说:
整数二进制有三种表示形式:原码,反码,补码
而对于正整数来说:原码,反码,补码相同。
对于负整数来说:原码,反码,补码是需要计算的。

就以a=-10为例,
先写原码
-10为负数,符号位就应该为1(正数就为0,负数就为1),10用二进制表示为1010

//原码
100000000000000000000000000000001010

反码就是符号位不变,将原码按位取反

//反码
111111111111111111111111111111110101

补码就是反码+1

111111111111111111111111111111110110

那么我们在内存中储存的究竟是-10的原码还是反码,还是补码呢?我们用监视的方法来看一下,如图2
图2
我们把数据提出来:FFFFFFF6→转换为2进制就为111111111111111111111111111111110110(比如最后四位对应6,6转换为2进制就为0110).

所以,整数在内存中的储存是以补码的形式储存的

那么为什么是存的补码而不是其他形式呢?我们举个例子:
我们首先要知道,编译器里是没有减法计算的,所谓的减法实际上还是加法运算,比如:1-1其实是1+(-1)

假设储存的是原码
 1的原码:
 00000000000000000000000000000000001
-1的原码:
 10000000000000000000000000000000001
 1+(-1)=10000000000000000000000000000000010
 这是-2的原码,与我们想得到的0不相符

所以原码储存是行不通的,我们再来试试补码

假设储存的是补码
1的补码:
 00000000000000000000000000000000001
 -1的补码:
 11111111111111111111111111111111111
 1+(-1)=:
 100000000000000000000000000000000000
 //多出的一位1丢掉变为
 00000000000000000000000000000000000
 这就是0的补码

所以只有用补码来计算才是正确的。
除此之外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。

到这里我们发现有一个问题没有被解决,那就是监视器中显示的明明是F6 FF FF FF,但我们在读的时候却是反着读的,这里就要涉及新的概念:大端和小端

大小端

我们来看一个地址的存放,如图3
图3
图中第一和第二种就是大端字节序和小端字节序,第三种和第四种方法虽然在理论上来讲也是可行的,但是存放的过程就会变得过于复杂,所以不采用。

大小端如何区分

图4

如图4,我们假设地址11 22 33 44为一个数字,那么越靠近右边,代表着位数越低,而越靠近左边,代表着位数越高,所以右边为低位字节,左边为高位字节
根据我们定义的左边为低地址,右边为高地址,
大端(存储)模式定义为:数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中
小端(存储)模式定义为:数据的低位保存在内存的低地址中,而数据的高位,保存在内存的高地址中

速记的口诀是:小同大异
那么通过我们所学的知识,上述图片中的F6 FF FF FF就为小端存储模式

为什么会有大小端

为什么会有大小端模式之分呢?这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为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处理器还可以由硬件来选择是大端模式还是小端模式。

判断机器字节序

我们通过设计一个小程序来判断当前机器的字节序
假设我们要存放的地址为 00 00 00 01

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

因为我们只想访问一个字节来判断是否为1,所以我们需要将&a强制转换为char类型,这样char就指向整形a的四个字节中的首个字节*。

我们同样可以通过函数的方法实现:

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

优化一下

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

三种方法运行结果如图4
图4
所以我的电脑采用的是小端存储模式

以上就是本章的全部内容了,如有出入,欢迎指正。

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

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

相关文章

Python深度学习实战PyQt5基本控件使用解析

PyQt5 提供了丰富的输入输出控件。本文介绍通过 QtDesigner 工具栏创建常用的基本控件,包括各种按钮控件、文本输入控件和调节输入控件1. PyQt5 控件简介1.1 什么是控件控件也称控件对象,是 Qt用户界面上最基本的组件类型,也是构成用户界面的…

作为研发如何使用Github Api?

文章目录使用步骤账号创建进行开发者相关设置API操作演示Github API好处推荐的Github API🌟个人主页: 个人主页 🚵‍♀️个人介绍:每天进步一点点,生活变得好一点点。 📌作为一位开发,不管是非工作的还是工作中的人士&…

指针的进阶

指针的进阶一级目录二级目录三级目录先来回顾一下:字符指针指针数组数组指针数组指针的定义&数组名vs数组名数组指针的使用数组参数 指针参数一维数组传参二维数组传参一级指针传参二级指针传参函数指针函数指针数组指向函数指针数组的指针回调函数指针和数组笔…

图表控件TeeChart for .NET系列教程六:选择一个系列类型(使用系列)

TeeChart for .NET是优秀的工业4.0 WinForm图表控件,官方独家授权汉化,集功能全面、性能稳定、价格实惠等优势于一体。TeeChart for .NET 中文版还可让您在使用和学习上没有任何语言障碍,至少可以节省30%的开发时间。 TeeChart for .NET最新…

python基于django的自媒体社区交流平台

自媒体社区平台采用python技术,基于django框架,mysql数据库进行开发,实现了以下功能: 本系统主要包括管理员,用户,商家和普通管理员四个角色组成,主要包括以下功能: 1;前台:首页、需求通告、优质案例、帮助中心、意见反馈、个人中心、后台管理…

区块链安全:从web3.0到数字货币

互联网发展的三个阶段 web1.0 静态页面,内容只能供用户去阅读,类似于在网络上读报纸或者看书。 web2.0 动态互联网,实现用户之间的互动,比如twitter,facebook,titok等。 web2.0中厂商用免费或极低的成…

基于UDP/TCP实现客户端服务器的网络通信程序

目录:前言基于UDP实现客户端服务器的网络通信程序基于TCP实现客户端服务器的网络通信程序前言网络编程的核心是Socket API,它是操作系统给应用程序提供的网络编程API,可以认为是socket api是和传输层密切相关的。在传输层里面,提供…

leetcode刷题---递归思想

leetcode刷题---递归思想)1.1 递归介绍1.2 基本步骤1.3 代表题目1.3.1 入门题---青蛙跳1.3.2.1 初级题226.翻转二叉树112.路径总和1.3.3 中级题---汉诺塔问题1.3.4 进阶题---细胞分裂1.1 递归介绍 如果在函数中存在着调用函数本身的情况,这种现象就叫递…

java Resource

参看本文前 你要先了解 spring中的 Autowired和Qualifier 注解 如果之前没有接触过 可以查看我的文章 java spring 根据注解方式按(类型/名称)注入Bean 然后 创建一个java项目 引入spring注解方式 所需要的包 然后 在src下创建包 我们这里直接叫 Bean 在Bean下创建包 叫UserD…

【GIC】处理中断

目录 一、当中断变为pending时发生了什么? 二、中断响应 三、虚假的中断 四、运行优先级&抢占 五、结束中断 六、检查系统的当前状态 6.1最高优先级等待中断和运行优先级 6.2单个INTID的状态 一、当中断变为pending时发生了什么? 前面的文章…

0207 事件

事件监听事件监听版本事件类型事件概念事件在编程时系统内发生的动作或者发生的事情例子点击按钮鼠标经过拖拽鼠标事件监听(注册事件,绑定事件)让程序员检测是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应…

PHP立体安全:一网打尽攻击向量

PHP立体安全:一网打尽攻击向量 所谓攻击向量,就是指黑传递有效负载或恶意结果而可以访问计算机或网络服务器的路径或方法。 PHP的安全并不只有危险函数, 这只是冰山一角 。本文将介绍PHP从汇编层面到框架层面直到标准层面的所有攻击向量。 攻…

【H5】html实现微信授权登陆

html实现微信授权登陆前言网页授权的两种 scope 的区别开发指南第一步:用户同意授权,获取code第二步:通过 code 换取网页授权access_token第三步:拉取用户信息(需 scope 为 snsapi_userinfo)代码实现:效果图总结前言 …

用Python出了3000道数学题,外甥表示要正月剪头

人生苦短,快学Python! 过年期间发现小外甥已经上小学了,我姐说老师今天给他们布置了寒假作业:每天坚持做乘法和加减法混合运算。 这我必须帮帮忙,用Python写了一段自动生成小学生计算题的代码,并支持导出…

Python入门之ChatGPT的API调(Python版)

一、Python环境部署 参考Python 环境搭建 | 菜鸟教程 Python官网:Welcome to Python.org Python文档下载地址:Our Documentation | Python.org 二、Thonny的安装 安装包地址:Thonny, Python IDE for beginners 三、ChatGPT的Key申请 网…

学Qt想系统的学习,看哪本书?

Qt 是一个跨平台应用开发框架(framework),它是用 C语言写的一套类库。使用 Qt 能为 桌面计算机、服务器、移动设备甚至单片机开发各种应用(application),特别是图形用户界面 (graphical user in…

虹科分享|在ntopng中使用多用户模式

并非所有 ntop 用户都知道 ntopng 本机实现了多用户支持。也就是说,您可以使用ntopng收集和分析来自多个用户的流量,并向每个用户显示自己的流量,隐藏其余所有流量。 您需要做的就是非常简单: 1. 启动 ntopng 并将其配置为接收受…

Python将字典转换为csv

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。喜欢通过博客创作的方式对所学的知识进行总结与归纳,不仅形成深入且独到的理…

设计模式C++实现4:装饰模式

前言 参考大话设计模式; 详细内容参见大话模式一书第六章,该书使用C#实现,本实验通过C语言实现。 装饰模式(Decorator),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰…

MapReduce工作原理

一.MapReduce工作流程图 1、分片操作:FileInputstream,首先要计算切片大小,FileInputstream是一个抽象类,继承InputFormat接口,真正完成工作的是它的实现类,默认为是TextInputFormat,TextInputF…