筑基七层 —— 数据在内存中的存储?拿来吧你

news2024/10/6 20:37:18

目录

零:移步

一.修炼必备

二.问题思考

三.整型在内存中的存储

三.大端字节序和小端字节序

四.浮点数在内存中的存储


零:移步

  CSDN由于我的排版不怎么好看,我的有道云笔记相当的美观,请移步至有道云笔记

一.修炼必备

 1.入门必备:VS2019社区版,下载地址:Visual Studio 较旧的下载 - 2019、2017、2015 和以前的版本 (microsoft.com)

 2.趁手武器:印象笔记/有道云笔记

 3.修炼秘籍:牛客网 - 找工作神器|笔试题库|面试经验|实习招聘内推,求职就业一站解决_牛客网 (nowcoder.com)

 4.雷劫必备:leetcode 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 

 注:遇到瓶颈怎么办?百度百科_全球领先的中文百科全书 (baidu.com)

二.问题思考

 1.C语言数据的类型?

 2.整数在计算机中二进制的表示形式有几种?正整数和负整数相同的吗?

 3.整数在内存中的存放的是什么?怎么验证是这样存放的?

 4.为什么计算机中存放的是补码?

 5.什么是字节序?

 6.数据的字节序是在内存中怎么存储的?

 7.如何判断一个数据的字节序是大端字节序还是小端字节序?

 8.浮点数在内存中的存储和整数的存储是一样的吗?

 9.浮点数的存储规则

三.整型在内存中的存储

 1.C语言数据的类型?

1)整型:char,short,int,long,long long

2)浮点型:float,double

3)构造类型:struct,union

4)指针类型:int*,char*,double*等

5)空类型:void(常用于函数的返回类型,指针类型,函数的参数)

 2.如何查看整数类型的值范围?

    ——在limits.h头文件中查看

 3.整数在计算机中二进制的表示形式有几种?正整数和负整数相同的吗?

  1)整数在计算机中的表示形式有:原码、反码、补码

  2)正整数的原码、反码、补码均相同

  3)负整数的原码、反码、补码的规则

原码:把整数直接按照二进制进行转化

反码:原码的符号位不变,其他位按位取反

补码:反码 + 1

#include <stdio.h>

//原码、反码、补码的转化规则
int main()
{
    //正整数的原码、反码、补码相同
    int num1 = 5;
    //00000000 00000000 00000000 00000101  num1的补码
    
    //负整数的原码、反码、补码转化
    int num2 = -5;
    //10000000 00000000 00000000 00000101  原码
    //(原码符号位不变,其他位取反)
    //11111111 11111111 11111111 11111010  反码
    //(反码+1)
    //11111111 11111111 11111111 11111011  补码
    return 0;
}

 4.如何证明整型在内存中存储的是补码?

    ——使用负数证明

  1)打印出负数的十六进制形式(十六进制是无符号的打印)

#include <stdio.h>

//证明整型在内存中存储的是补码
int main()
{
    int num1 = 1;
    //00000000 00000000 00000000 00000001   1的补码
    int num2 = -1;
    //11111111 11111111 11111111 11111111  -1的补码
    //注:每四个2进制位可以组成一个十六进制:ffffff
    printf("%x\n", num1);//1
    printf("%x\n", num2);//fffffff
    return 0;
}

  运行结果如图:

  2)调试查看负数在内存中的存储形式 

 5.为什么计算机中存放的是补码? 

1)方便运算:省去了计算机判断符号位或判断+/-运算的麻烦,采用补码后,不管是加法还是减法均是使用加法进行运算(CPU只有加法器)

2)更加标准:保证了系统的编码的一致性和连续性,也同时避免了+/-0的麻烦 

 6.practice

  case 1:思考并分析

#include <stdio.h>

int main()
{
    char a = -1;
    //默认是有符号数
    //10000001 原码
    //11111110 反码
    //11111111 补码
    //11111111 11111111 11111111 11111111 整型提升
    //11111111 截取(补码)
    //10000001 原码(-1)
    
    signed char b = -1;
    //b 和 a一样
    
    unsigned char c = -1;
    //10000001 原码
    //11111110 反码
    //11111111 补码
    //11111111 11111111 11111111 11111111 整型提升
    //11111111 截取 --无符号数:255
    
    printf("a=%d,b=%d,c=%d\n", a, b, c);//-1 -1,255
    return 0;
}

  运行结果如图:

  case 2:思考并分析 

#include <stdio.h>

int main()
{
    char a = -128;
    //10000000 -- 补码
    //因为是无符号整型打印,需要整型提升
    //11111111 11111111 11111111 10000000  -- 4294967168(结果)
    printf("%u\n", a);//4294967168
    return 0;
}

  运行结果如图:

  case 3:思考并分析

#include <stdio.h>

int main()
{
    char a = 128;
    //10000000
    //11111111 11111111 11111111 10000000 整型提升
    //-- 4294967168(结果)
    printf("%u\n", a);//4294967168
    return 0;
}

  运行结果如图:

  case 4:思考并分析 

#include <stdio.h>

int main()
{
    int a = -20;
    //10000000 00000000 00000000 00010100 原码
    //11111111 11111111 11111111 11101011 反码
    //11111111 11111111 11111111 11101100 补码
    unsigned int b = 10;
    //11111111 11111111 11111111 11101100 补码(-20)
    //00000000 00000000 00000000 00001010 补码 (10)
    //11111111 11111111 11111111 11110110 运算结果(补码)
    //11111111 11111111 11111111 11110101
    //10000000 00000000 00000000 00001010  -10:结果
    printf("%d\n", a + b);
    return 0;
}

  运行结果如图:

  case 5:思考并分析 

#include <stdio.h>

int main()
{
    unsigned int i;
    //为什么进行了死循环?
    //i是无符号整型
    //i = 0;执行i--的时候
    //00000000 00000000 00000000 00000000  0的补码
    //11111111 11111111 11111111 11111111  -1的补码(无符号数,最高位没有正负之分)
    //4294967295(-1的时候的值)
    for (i = 9; i >= 0; i--)
    {
        printf("%u\n", i);
    }
    return 0;
}

  运行结果如图:

  case 6:思考并分析 

#include <stdio.h>
#include <string.h>

int main()
{
    char a[1000];
    int i;
    for (i = 0; i < 1000; i++)
    {
        a[i] = -1 - i;
        //11111111  -1的补码
        //11111110  -2的补码
        //11111101  -3的补码
        //……
        //10000000  -128的补码
        //01111111   127的补码
        //……
        //00000000   0的补码('\0')
    }
    printf("%d\n", strlen(a));//255
    return 0;
}

  一图了解char的范围:

  运行结果如图:

  case 7:思考并分析

#include <stdio.h>

unsigned char i;
int main()
{
    for (i = 0; i <= 255; i++)
    {
        printf("hehe\n");
        //11111111 i为255的时候
        //00000000 255+1后的值
        //所以为死循环
    }
    return 0;
}

  运行结果如图:

三.大端字节序和小端字节序

 1.什么是字节序?

    ——字节序又称为端序或尾序,指计算机内存中多字节数据在内存中的排列顺序

 2.数据的字节序是在内存中怎么存储的?

    ——浮点数和整数的字节序都有大端和小端两种字节序

1)小端字节序

        ——数据的低位字节存储在内存的低地址处,高位字节存储在内存的高地址处

2)大端字节序

        ——数据的低位字节存储在内存的高地址处,高位字节存储在内存的低地址处

 3.如何判断一个数据的字节序是大端字节序还是小端字节序?

    ——内存中查看该数据的存储形式,看低位存放在内存中的位置

  图解:

  代码解释:

#include <stdio.h>

int main()
{
    int num = 0x11223344;
    float data = 5.5;
    //101.1
    //01000000101100000000000000000000
    //40b00000:十六进制形式
    return 0;
}

  小端字节序在内存中的图解:

  大端字节序在内存中的图解: 

 4.一道笔试题加强巩固

    ——请判断一个机器是大端字节序还是小端字节序

思路分析:我们只需要判断取出1的最低位即可,如果是0,则是大端存储序列,如果是1,则是小端字节序

#include <stdio.h>

//判断当前机器是大端还是小端字节序
int main()
{
    int a = 1;
    char* p = (char*)&a;
    
    if (*p == 1)
    {
        printf("小端字节序\n");
    }
    else
    {
        printf("大端字节序\n");
    }
    return 0;
}

   代码是写出来了,但是这样写是不是有点太low了,我们换种方式

#include <stdio.h>

//判断当前机器是大端还是小端字节序
int judge(int a)
{
    char* p = (char*)&a;
    return *p;//如果小端,直接返回1,大端返回0
}

int main()
{
    int a = 1;

    if (judge(a) == 1)
    {
        printf("小端字节序\n");
    }
    else
    {
        printf("大端字节序\n");
    }
    return 0;
}

  运行结果如图:

 

四.浮点数在内存中的存储

 1.怎么查看浮点数的值范围?

    ——在float.h头文件中查看

 

 2.浮点数的存储规则

  1)浮点数进行存储的形式:(-1)^S * M * 2^E;

    ——解释:S表示符号位,M表示有效数字:1

  2)在IEEE的规定下,最高位的1位S表示符号位,接下来的八位表示指数E,剩下的23位表示有效数字M

   float图解:

   double图解:

  3)由图知:float的指数位有8位,double的指数位有11位,float的M有23位,double的M有52位

  4)IEEE对M和E还有一些特别的规定

   i.因为1

   ii.指数E是一个无符号整数(unsigned int)

a.float的话,E的值在0~255之间;double的话,E的值在0~2047之间

b.注意,科学计数法中的E是可以是为负数的,所以我们在计算E的时候,应该加上一个中间值,float类型+127,double类型+1023

   iii.E从内存中取出的三种情况

a.E不为全0或全1

        ——使用E转化的十进制值减去127/1023得到真实值,在给有效数字加上小数点前面的1(常用)

b.E全为0

        ——E的值是1-127或1-1023,得到真实值,这个时候我们不需要在加上小数点前面的1了,这样做是为了表示正负0,以及接近0的很小的数值

c.E全为1

        ——这时,如果有效数字全为0,表示±无穷大(正负取决于符号位s)

 3.practice

  case 1:分析解释下面代码 

#include <stdio.h>

int main()
{
    int num = 9;
    float* p = (float*)&num;
    
    printf("%d\n", num);//9
    printf("%f\n", *p);//0.000000
    //分析为什么是0.000000
    //00000000 00000000 00000000 00001001  9的补码
    //浮点数中看到的形式
    //0 00000000 00000000000000000001001
    //相当于0.00000000000000000001001 * (1 - 2^-126)
    //这个数非常小,而浮点数默认取小数点后6位,所以为0.000000
    
    *p = 9.0;
    //1001.0
    //1.001 * 2^3
    //S = 0,E = 2, M = 1.001
    //可以写出*p的的二进制序列
    //0 10000010 00100000000000000000000 *p的二进制序列
    //化为整数:1091567616
    printf("%d\n", num);//1091567616
    printf("%f\n", *p);//9.000000
    return 0;
}

  运行结果如图:

  case 2:分析并解释

#include <stdio.h>

int main()
{
    float num = 5.5;
    //101.1 --> 1.011
    //S = 0,E = 2, M = 1.011 --> 得出二进制序列
    //0 10000001 01100000000000000000000  num的二进制序列
    int* p = (int*)&num;
    //01000000101100000000000000000000  结果:1085276160
    printf("%f\n", num);//5.500000
    printf("%d\n", *p);//1085276160
    
    *p = 5;
    //01000000 10110000 00000000 00000000序列变为:
    //00000000 00000000 00000000 00000101  5
    //转化为float类型
    //0 00000000 00000000000000000000101  
    //结果:0.00000000000000000000101 * 2 ^ (-126);(极小的数)
    //转为float即为0.000000
    printf("%f\n", num);//0.000000
    printf("%d\n", *p);//5
    return 0;
}

  运行结果如图:

  !!!恭喜你,突破至筑基七层!!!

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

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

相关文章

web客户端-websocket

1、websocket简介 WebSocket是HTML5开始提供的一种在单个TCP连接上进行全双工通讯的协议。 WebSocket使得客户端和服务器之间的数据交换变得更加简单&#xff0c;允许服务端主动向客户端推送数据。在WebSocket API中&#xff0c;浏览器和服务器只需要完成一次握手&#xff0c…

一文教你把ChatGPT变成MySQL数据库,颠覆你的认知

ChatGPT是当前最热门的产品了,很多人已经在用ChatGPT问答、写文章、编程、做题甚至是通过了各种考试。今天我用几个步骤来带着大家体验如何把ChatGPT变成MySQL数据库。 首先,我们需要创建一个数据库,让chatgpt把自己当做一个数据库,可以给它一个定义: 你来充当一个mysql数…

自定义复杂图片水印

我的社交能力还不如5岁儿童和狗。 文章目录前言一、主要工具类总结前言 之前写过一些简单的图片压缩和图片加水印&#xff1a;JAVA实现图片质量压缩和加水印 本次主要是针对图片加水印进行一个升级&#xff0c;图片水印自定义&#xff0c;自适应大小。 来&#xff0c;先看几…

JS语法让人困惑的点 “==与===”

在JS中有很多神奇的语法&#xff0c;非常让人困惑&#xff0c;我们就先一一道来&#xff0c;相信你在开发中或多或少都踩过这些坑&#xff0c;或者让人无法理解。 今天我们就来说下【】和【】 这题对于很多没有系统学过前端开发的技术人员来说&#xff0c;算个重点&#xff0c…

LLFlow沦为和代码解读

LLFlow沦为和代码解读 1.测试时代码的运行位置 sr&#xff1a;什么意思 sr 和 z 这里又将模型设置为了训练模式 所以下面这部分代码应该是测试时运行的所有代码 这个就是测试时使用的网络模型框架 下面应该就是self.netG的网络模型框架 但是这个z的网络模型框架代码还不…

前端基础之HTML扫盲

文章目录一. 第一个HTML程序1. 创建一个HTML文件并运行2. HTML的基本结构二. HTML常见标签1. 注释标签2. 标题标签3. 段落标签4. 换行标签5. 格式化标签6. 图片标签7. 超链接标签8. 表格标签9. 列表标签10. 表单标签10.1 input标签10.2 select标签10.3 textarea标签11. 无语义标…

Outlook账号被封?别慌,一步步教你怎么申诉

相信很多兄弟们使用Outlook不止是为了注册第三方平台&#xff0c;很多时候还会用来发送一些营销广告。但是广告邮件发多了很容易被官方检测到并查封。龙哥考虑到这个问题&#xff0c;就干脆给兄弟们也出一份Outlook的申诉教程&#xff0c;保证大家都从注册、养号、防关联到解封…

DataGear 使用数据集计算属性功能制作数据可视化图表

DataGear 在4.5.0版本新增了数据集计算属性特性&#xff0c;支持在定义数据集时对原始数据进行二次计算处理。 利用这一特性&#xff0c;可以更加方便灵活地制作数据可视化图表。 本文以某公司近两年季度销售额Excel为例&#xff0c;介绍如何基于数据集计算属性功能制作数据可…

Vue跨级通信(重点)

当不使用Vuex的前提下&#xff0c;子孙传递就得使用另外一种办法&#xff1a;provide 和 inject 总结&#xff1a;provide / inject 类似于消息的订阅和发布。- inject接收数据。- provide提供或发送数据&#xff0c;&#xff08;1&#xff09;provide&#xff08;name&#xf…

Dubbo性能调优参数以及原理

Dubbo作为一个服务治理框架&#xff0c;功能相对来说比较完善&#xff0c;性能也挺不错。但很多同学在使用dubbo的时候&#xff0c;只是简单的参考官方说明进行配置和应用&#xff0c;并没有过多的去思考一些关键参数的意义&#xff0c;最终做出来的效果总是差强人意,接下来我们…

扬帆优配|反弹涨超70%,昨收三连板,稀土行业或迎大事件

本年第一批稀土挖掘锻炼目标行将发放。 2月22日晚&#xff0c;东易日盛公告称&#xff0c;公司收到董事、副总经理兼财务总监李双侠出具的《关于未严格执行股份减持方案的致歉函》&#xff0c;其此次减持方案已施行结束&#xff0c;但在施行减持方案时&#xff0c;因操作失误&a…

从没想过开源 API 工具的 Mock 功能,这么好用

很多时候&#xff0c;接口尚未开发完成&#xff0c;在系统交互双方定义好接口之后&#xff0c;我们可以提前进行开发和测试&#xff0c;并不依赖上游系统的开发实现。 通过使用Mock模拟数据接口&#xff0c;我们即可在只开发了UI的情况下&#xff0c;无须服务端的开发就可以进行…

证明CPU指令是乱序执行的

承接上文CPU缓存一致性原理双击QQ.exe从磁盘加载到内存里面&#xff0c;内存里面就会有了一个进程&#xff0c;进程产生的时候会产生一个主线程&#xff0c;就是main方法所在的线程&#xff0c;cpu会找到main开始的地方&#xff0c;把它的指令读取过来放到程序计数器&#xff0…

从功能测试进阶自动化测试,熬夜7天整理出这一份3000字超全学习指南

一、为什么要学习自动化测试&#xff1f; 如果在前两年&#xff0c;可能10个测试员有6个都是做的功能测试&#xff0c;但随着测试技术的发展以及测试工作的深入&#xff0c;传统的手工测试已经无法满足多模块的测试需求&#xff0c;所以为了提高测试效率和测试质量&#xff0c…

关于 mac 本地配置域名能 ping 通,但是浏览器不能访问的问题(而其他电脑操作可访问)

关于 mac 本地配置域名能 ping 通&#xff0c;但是浏览器不能访问的问题&#xff08;而其他电脑操作可访问&#xff09;1. 配置域名的方式1.1 sudo vim /etc/hosts1.2 浏览器插件 LiveHosts2. 问题描述3. 解决问题方法3.1 尝试方法1—确保代理都关闭3.2 尝试方法2—确保域名能p…

一文学会 Spring 整合 MyBatis

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

js闭包简单理解

js里面的闭包是一个难点也是它的一个特色&#xff0c;是我们必须掌握的js高级特性&#xff0c;那么什么是闭包呢&#xff1f;它又有什么作用呢&#xff1f; 1&#xff0c;提到闭包我们这里先讲解一下js作用域的问题 js的作用域分两种&#xff0c;全局和局部&#xff0c;基于我…

代码随想录第十六天(347、194、195、94)

347. 前 K 个高频元素 答案 思路&#xff1a; 1、首先&#xff0c;用到了每个值对应的出现次数&#xff0c;想到要用哈希map存放 2、还需要将出现频率从大到小进行排序&#xff0c;找出前k个元素 3、时间复杂度应该比O&#xff08;nlogn&#xff09;小 如果想用快速排序&…

黑盒渗透盲打lampiao

一、查找主机ip&#xff0c;通过Nmap扫描工具排查出我的靶机的IP 为.134 python tools.py ip -i 192.168.12.0 -h 254 -l 1 二、扫描其他端口。 1898 三、查看网站漏洞情况&#xff0c;典型的漏洞特征 Ac扫描漏洞情况&#xff0c;利用典型的漏洞。 四、开始getshell 1、启动M…

SigmaPlot科学绘图工具:ROC曲线分析及AUC组间差异的显著性分析

目的 初步使用SigmaPlot科学绘图工具&#xff1b;进行ROC曲线绘制并分析检验变量AUC组间差异性是否显著 软件下载及安装 SigmaPlot下载安装按照这个教程即可&#xff1a;https://www.hhkxxw.com/24799.html 快速通道&#xff1a;SigmaPlot下载链接&#xff1a;百度网盘链接…