C语言-----数据在内存中的存储(1)

1.整数在内存中的存储

我们之前就了解过整数的二进制写法分别有3种,分别为原码,反码,补码。整型在内存中存储的是补码。

原码,反码,补码都有自己的符号位和数值位,符号位为1时,则表示负数,符号位为0时,则表示正数。

注意:

正数的原码,反码,补码相同。

而负数的原码,反码,补码是不一样的。

负数的原码就是将其数字转换为二进制,得到原码。

对原码除符号位外的数值位进行取反,得到反码。

反码+1 得到补码。

以上是有负数的原码得到其补码的过程。

由负数的补码得到原码也可以通过 对补码进行取反加1得到其原码。

2.大小端字节序和字节序判断

我们先看一段简单的代码

如下图

变量a原本设置的是0x11223344,可通过vs编译器调试发现,其在内存中的存储顺序恰好是反过来的。

这是为什么呢?

这就涉及到来大小端字节序的问题。 

2.1 大小端的含义

首先我们要清楚当储存的数据大小超过一个字节时,其在内存中的存储顺序就有了大端字节序存储和小端字节序存储。

1.大端字节序存储:是指数据的低字节内容保存在内存中的高地址处,而高细节内容保存在内存中的低地址处。

如图,11相对于22来说,11是高字节内容,22是低字节内容。

所以将11放在低地址处,22放在放在高地址处。33和44依此类推。

2. 小端字节序存储:是指数据的低字节内容保存在内存中的低地址,而高字节内容保存在内存中的·高地址处。

如图

通过以上了解的内容可知,为什么数据在vs中调试,在内存中的存储顺序是倒过来的。

原因是vs是小端字节序存储。 

2.2 判断大小端字节序

虽然我们知道了vs是小端字节序存储,那我们如何来证明呢?

我们可以通过代码来实现

int system()
{int a = 1;char* p = &a;return *p;
}
int main()
{int ret = system();if (ret == 1){printf("小端字节序存储");}else{printf("大端字节序存储");}return 0;
}

看图

如上图所示,a的16进制位分别在大端字节序和小端字节序的顺序排序。

我们又设计了一个char* p指针来存储a,所以p指向了a的第一个字节的内容,当我们对p进行解引用时,一次也只能访问一个字节,而一个字节恰好是2个16进制位。

返回*p的值,用ret来保存*p,我们就可以通过ret的值来判断大小端字节序存储了。

当返回值位1时,是小端字节序存储,返回值位0时,是大端字节序存储。

用vs运行代码

3.练习题

接着来几道练习题巩固一下知识。

练习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,c  三个变量,分别是char ,signed char, unsigned char 类型。

这时很疑惑,明明是 -1 是个整型数据,却用了一个不符合整型类型的变量来存储。

但这是允许的。只不过会发生数据的截断,影响最终打印的结果。

这种题思路是一样的。

我们先以a为例

我们先把 -1 的原码写出来,为1000000000000000000000000001,

在对其取反,为 11111111111111111111111111111110,得到反码。

在对反码加1得到补码,为11111111111111111111111111111111,便是-1的补码。

我们知道整型数据在内存中是以补码的形式存储的,但是由于变量a是char类型的,所以a只能存储一个字节大小的数据,也就是8个比特位。则会发生数据的截断。

优先截断低字节的数据,这时便会截断8个比特位的内容存储到a中。

则这时a中存储的是11111111

(补充:char类型是signed类型的还是unsigned类型的是取决于编译器的,再vs中char默认为是signed char 类型的。) 


最后我们要以整型打印,所以要对a进行整型提升。

(整型提升规则:有符号数据补符号位,无符号数据不0)

由于a是signed char 型,属于有符号型,则对a进行整型提升后为:

11111111111111111111111111111111  

整型提升后得到的还是补码。所以我们要求出其原码。

接着对补码进行取反+1的操作的到原码:

10000000000000000000000000000001

由于是以%d的形式打印,也就是将a看作有符号数据,所以此时的最高位为符号位。

通过原码计算可知,最终a的值为 -1。

接着来分析b

由于b的类型和a在vs中的数据类型是一样的,并且赋值都为-1,所以和以上a的推算是一模一样的。

最后来分析c

一样的步骤,把 -1 的原码写出来  , 为 1000000000000000000000000001(原码)

接着对原码取反,为  11111111111111111111111111111110 (反码)

反码加1得到补码,为  11111111111111111111111111111111(补码)

也由于 c 是unsigned char 类型的,只能存储一个字节大小的数据,也就是8个比特位。

则发生截断

这时c存储的是11111111。

接着对其进行整型提升,由于c是unsigned char  类型,则此时最高位不是符号位了,所以补0.

得到 00000000000000000000000011111111  ,此时得到的也是补码。

但由于c是无符号数据,则原码,反码,补码,相同。

通过原码计算得 c为255。

运行代码

练习2

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

一开始看到这道题,是肯定会懵一下的。不过别慌张,冷静分析。

这里涉及到一个循环,后面有涉及到了一个strlen的计算,我们知道strlen计算的是 '/0' 之前的长度。而 \0 的ASCII值为0,所以计算的是0之前的长度。

遇到这种题,有一个圆形图解法。下面是char 的圆图。

 

如上图,我们对二进制的+1弄成一个圆,也就是循环了。

由于题目是减1,那就反过来,则0的前面就有255个,则长度就为255. 

运行代码,如下图,也是255.

练习3

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

这也可以根据圆形图解法来解决,不过是unsigned char 类型的圆

 

由此得出 i 的 取值范围 0~255,所以 i 永远小于等于255,则循环条件恒成立,这样就会现如死循环。

练习4

#include <stdio.h>
int main()
{int a[4] = { 1, 2, 3, 4 };int *ptr1 = (int *)(&a + 1);int *ptr2 = (int *)((int)a + 1);printf("%x,%x", ptr1[-1], *ptr2);return 0;
}

这道题是有点复杂的,我们还是冷静分析。

线分析ptr1,如下图

由上图轻易得到ptr[-1]为4。

难点就在ptr2

我们知道数组名在大部分就是条件下是首元素地址,所以此时a是首元素地址 ,但是被强制转换成int 类型了,强制转换成 int 型后进行加1,我们知道整型加1和整数加1的道理差不多,这时加1就是跳过了1个字节。我们将数组的内容转换成16进制的形式。

上面分析得知,整型加1就是跳过一个字节,而2个16进制位就是一个字节。而a中又是int类型的,存了4个字节的数据。如下图所示

但又因为在vs中是小端字节序存储,所以我们要将ptr2还原。

还原得到  02000000。

运行代码,如下图

 

 

 

 

 

 

 

 

 

 

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

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

相关文章

【Docker笔记05】【网络模式】

一、前言 本系列是根据 B 站 尚硅谷 Docker 视频 学习记录笔记。因为没有视频课件&#xff0c;部分内容摘自 https://www.yuque.com/tmfl/cloud/dketq0。 本系列仅为自身学习笔记记录使用&#xff0c;记录存在偏差&#xff0c;推荐阅读原视频内容或本文参考笔记。 二、简单介…

通用开发技能系列:Authentication、OAuth、JWT 认证策略

云原生学习路线导航页&#xff08;持续更新中&#xff09; 本文是 通用开发技能系列 文章&#xff0c;主要对编程通用技能 Authentication、OAuth、JWT 认证策略 进行学习 1.Basic Authentication认证 每个请求都需要将 用户名密码 进行base64编码后&#xff0c;放在请求头的A…

基于隐私保护的可追踪可撤销密文策略属性加密方案论文阅读

论文是2022年发表的A Traceable and Revocable Ciphertext-Policy Attribute-based Encryption Scheme Based on Privacy Protection 摘要 本篇论文提出了一种具有用户撤销、白盒追踪、策略策略隐藏功能的CP-ABE方案。在该方案中密文被分为两个部分&#xff1a;第一个部分是和…

基于springboot实现教师人事档案管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现在线商城系统演示 摘要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本ONLY在线商城系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理…

第六期丨酷雷曼无人机技能培训

第6期无人机技能提升培训 盼望着盼望着&#xff0c;第六期无人机技能提升培训会终于如期和大家见面了。 2024年1月1日&#xff0c;国务院、中央军事委员会颁布《无人驾驶航空器飞行管理暂行条例》&#xff0c;对民用无人机飞行活动实施更为严格的规范约束&#xff0c;越来越多…

阿里云服务器安装Java开发环境最佳实践

服务器环境安装 环境依赖服务器配置配置SSH登录打开安全配置端口远程连接配置秘钥 Linux服务器常用指令向远程服务器传送文件systemctl 相关 安装MySql安装步骤step1 检查并清除以前的mysql相关文件step2 安装step3 MySQL参数配置step4 设置开机启动step5 初始化数据库step6配置…

ABAP开发中常用弹窗的应用详解

在ABAP程序设计中为提示和交互的需要会经常用到弹窗&#xff0c; 所谓弹窗就是弹出一个框&#xff0c;告诉用户什么事情、需要确认什么、或者让用户输入什么内容等等&#xff0c;它价值在于通过提示、提醒、警告&#xff0c;帮助用户顺利完成业务流程中的必要操作或给用户提供实…

【JS】打乱数组顺序,用作领域:随机播放音乐

思路 循环数组随机获取数组下标取值&#xff1a; 取当前随机下标数组取当前循环的下标数组 相互替换步骤3的数组 /*** 随机数组顺序* param {Array} arr 数组* returns Array*/ const shufArr arr > {for (let i arr.length - 1; i > 0; i--) {const j Math.floor(M…

中国智慧城管哪家做的好?

智慧城市管理综合执法系统建立全市统一的法律法规、裁量基准、执法事项、执法文书和基础信息库&#xff0c;实现从获取线索、立案、调查、处理到结案全过程的信息化和文书制作的智能化。全面支持移动执法办案&#xff0c;提高执法效率。 技术架构&#xff1a; 微服务javasprin…

中颖51芯片学习1. 系统时钟及IO口输出操作

中颖51芯片学习1. 系统时钟及IO口输出操作 一、芯片介绍1. 规格2. 资源3. 中断源&#xff1a;4. 方框图5. 封装&#xff08;1&#xff09;32脚LQFP封装&#xff08;2&#xff09;28脚SOP封装&#xff08;3&#xff09;20脚SOP封装 二、开发环境搭建1. 安装keil2. 安装中颖keil插…

安全测试重点思考(中)--如何防止漏洞XSS和CSRF漏洞

如何防止漏洞XSS和CSRF漏洞 XSS漏洞的预防springsecurity框架来预防xss漏洞的步骤将特殊字符进行实体转义使用类库和修改cookie属性使用安全的HTTP Only Cookie使用安全的Cookie使用CSP&#xff08;内容安全策略&#xff09;使用专门的XSS防护库输入验证和过滤 XSS的面试题你对…

4.2总结

了解了部分Api的使用并学习了接口的API API API包含了较多种类&#xff08;System,Runtime等&#xff09; System其实就是一个工具类&#xff0c;提供了一些与系统相关的方法 下面有一些常间的System方法 方法名说明public static void exit (int status)终止当前运行的ja…

深入浅出 -- 系统架构之微服务架构常见的六种设计模式

面向服务的架构&#xff08;SOA&#xff09; 面向服务的架构&#xff08;SOA&#xff09;是一种设计方法&#xff0c;也是一个组件模型&#xff0c;它将应用程序的不同功能单元&#xff08;称为服务&#xff09;通过这些服务之间定义良好的接口和契约联系起来。接口是采用中立的…

HarmonyOS应用开发ArkUI(TS)电商项目实战

项目介绍 本项目基于 HarmonyOS 的ArkUI框架TS扩展的声明式开发范式&#xff0c;关于语法和概念直接看官网官方文档地址&#xff1a;基于TS扩展的声明式开发范式&#xff0c; 工具版本&#xff1a; DevEco Studio 3.1 Canary1 SDK版本&#xff1a; 3.1.9.7&#xff08;API V…

春招3月面试题的总结--南京,山东,西安,东莞四家公司总结。

1.南京某公司 1.Java的几种基本数据类型&#xff1f;分别是多少字节&#xff1f; byte&#xff0c;8bit 1字节 char&#xff0c;16bit 2字节 short&#xff0c;16bit 2字节 int&#xff0c;32bit 4字节 float&#xff0c;32bit 4字节 long&#xff0c;64bit 8字节 doubl…

睿尔曼-具身智能双臂主从手项目方案

具身智能双臂主从手项目方案 一、公司介绍 成立于2018年&#xff0c;是一家专注于超轻量仿人机械臂研发、生产及销售的国家级高新技术企业。总部位于北京石景山区首特产业园&#xff0c;工厂坐落于江苏省常州科教城智能数字产业园&#xff0c;团队的核心成员毕业于北京航空航…

前端验证码

一、基础验证码 gVerify.js&#xff1a; !(function (window, document) {function GVerify(options) { //创建一个图形验证码对象&#xff0c;接收options对象为参数this.options { //默认options参数值id: "", //容器IdcanvasId: "verifyCanvas", //ca…

c++11 标准模板(STL)本地化库 - 平面类别 - (std::ctype) 定义字符分类表(三)

本地化库 本地环境设施包含字符分类和字符串校对、数值、货币及日期/时间格式化和分析&#xff0c;以及消息取得的国际化支持。本地环境设置控制流 I/O 、正则表达式库和 C 标准库的其他组件的行为。 平面类别 定义字符分类表 std::ctype template< class CharT > clas…

【nc工具信息传输】

nc&#xff0c;全名叫 netcat&#xff0c;它可以用来完成很多的网络功能&#xff0c;譬如端口扫描、建立TCP/UDP连接&#xff0c;数据传输、网络调试等等&#xff0c;因此&#xff0c;它也常被称为网络工具的 瑞士军刀 。 nc [-46DdhklnrStUuvzC] [-i interval] [-p source_po…

Linux系统Docker搭建Wiki.Js应用程序并结合cpolar实现公网访问内网知识库

文章目录 1. 安装Docker2. 获取Wiki.js镜像3. 本地服务器打开Wiki.js并添加知识库内容4. 实现公网访问Wiki.js5. 固定Wiki.js公网地址 不管是在企业中还是在自己的个人知识整理上&#xff0c;我们都需要通过某种方式来有条理的组织相应的知识架构&#xff0c;那么一个好的知识整…