目录

  • 前言
  • 一、 数据类型详细介绍
    • 1.1 类型的基本归类:
  • 二. 整形在内存中的存储
    • 2.1 原码、反码、补码
    • 2.2 大小端介绍
    • 2.3 练习
  • 三. 浮点型在内存中的存储
    • 3.1 引例
    • 3.2 浮点数存储规则
    • 3.3引例解释
  • 总结

前言

学习了这么久的c语言,一直很好奇数据在内存的存储是怎么样的,经过自己的学习,特此写一篇总结来阐述自己对于数据存储的理解。


一、 数据类型详细介绍

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

类型的意义:

  1. 使用这个类型开辟内存空间的大小(大小决定了使用范围)。
  2. 如何看待内存空间的视角。

1.1 类型的基本归类:

整形家族:

浮点数家族:

构造类型:

指针类型:

空类型:

二. 整形在内存中的存储

2.1 原码、反码、补码

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

负整数的三种表示方法各不相同。
原码:
直接将数值按照正负数的形式翻译成二进制就可以得到原码。
反码:
将原码的符号位不变,其他位依次按位取反就可以得到反码。
补码:
反码+1就得到补码。
对于整形来说:数据存放内存中其实存放的是补码。
为什么呢?

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

2.2 大小端介绍

我们看看在内存中的存储:

我们可以看到对于a和b分别存储的是补码。但是我们发现顺序有点不对劲。

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

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

2.3 练习

【1】signed char 和 unsigned char

int main()
{char a = -1;//-1 是整数 32bit位//10000000000000000000000000000001 - 原码//11111111111111111111111111111110 - 反码//11111111111111111111111111111111 - 补码//因为char只占8个bit位,所以发生截断,只保留低8位//11111111 - a - 截断//因为打印的是%d,是有符号的整数,所以要发生整型提升,按照符号位提升//11111111111111111111111111111111 - 补码 - 提升//10000000000000000000000000000001 - 原码//-1signed char b = -1;//signed char 与 char是一样的unsigned char c = -1;//10000000000000000000000000000001 - 原码//11111111111111111111111111111110 - 反码//11111111111111111111111111111111 - 补码//11111111 - c - 截断//因为是unsigned char,最高的一位是看做有效位来进行计算的,不是符号位//00000000000000000000000011111111 - 补码 - 整型提升//00000000000000000000000011111111 - 原码//255printf("a=%d b=%d c=%d", a, b, c); //-1 -1 255//%d是打印有符号的整数return 0;
}

【2】打印%u

#include <stdio.h>
int main()
{char a = -128;//10000000000000000000000010000000 - 原码//11111111111111111111111101111111 - 反码//11111111111111111111111110000000 - 补码//截断,char只能保留8个比特位//10000000 - a//看a本身的类型是signed char,是有符号的char,那么就按照符号位进行整型提升//11111111111111111111111110000000 - 整型提升//因为%u打印的是无符号的整形,那么就不会把原本的补码看做是一个有符号的整型,而是看做一个无符号的整型,直接打印//4294967168printf("%u\n", a);//%u打印的是无符号整形char b = 128;//00000000000000000000000010000000 - 原码、反码、补码//因为char b只存8个bit位,所以只存低八位//100000000 - 截断//char 为有符号整型,所以根据符号位进行整型提升//11111111111111111111111110000000 - 整型提升//因为%u打印的是无符号的整形,那么就不会把原本的补码看做是一个有符号的整型,而是看做一个无符号的整型,直接打印//4294967168printf("%u\n", b);//%u打印的是无符号整形return 0;
}

【3】signed+unsigned

#include<stdio.h>int main() {int i = -20;//10000000000000000000000000010100 - 原码//11111111111111111111111111101011 - 反码//11111111111111111111111111101100 - 补码unsigned int j = 10;//00000000000000000000000000001010 - 原码、补码、反码printf("%d\n", i + j);//%d是打印有符号整型//i + j//11111111111111111111111111110110 - 补码//11111111111111111111111111110101 - -1//10000000000000000000000000001010 - 原码//-10return 0;
}

【4】无符号死循环打印

#include<stdio.h>
#include<windows.h>int main() {unsigned int i;//无符号整数,i永远大于等于0for (i = 9; i >= 0; i--) //结束循环的条件为i>=0,而unsigned是永远大于等于0{printf("%u\n", i);Sleep(1000);}return 0;
}

【5】strlen找字符串长度

#include<stdio.h>int main()
{char a[1000];int i;for (i = 0; i < 1000; i++){a[i] = -1 - i;}//在字符0之前已经相加等于0,128+127=255//-1 -2 -3 -4 -5 …… -128 127 …… 5 4 3 2 1 0 -1 -2 ……printf("%d", strlen(a));//strlen找'\0'才停止,而'\0'的ASCII码值就为0return 0;
}

三. 浮点型在内存中的存储

常见的浮点数:
3.14159
1E10
浮点数家族包括: float、double、long double 类型。

3.1 引例

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

输出的结果是什么呢?

3.2 浮点数存储规则

num 和 *pFloat 在内存中明明是同一个数,为什么浮点数和整数的解读结果会差别这么大?
要理解这个结果,一定要搞懂浮点数在计算机内部的表示方法。
详细解读:
根据国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数V可以表示成下面的形式:
(-1)^S * M * 2^E
(-1)^S表示符号位,当S=0,V为正数;当S=1,V为负数。
M表示有效数字,大于等于1,小于2。
2^E表示指数位。
举例来说:
十进制的5.0,写成二进制是 101.0 ,相当于 1.01×2^2 。
那么,按照上面V的格式,可以得出S=0,M=1.01,E=2。
十进制的-5.0,写成二进制是 -101.0 ,相当于 -1.01×2^2 。那么,S=1,M=1.01,E=2。
IEEE 754规定:
对于32位的浮点数,最高的1位是符号位s,接着的8位是指数E,剩下的23位为有效数字M。

对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M。

IEEE 754对有效数字M和指数E,还有一些特别规定。
前面说过, 1≤M<2 ,也就是说,M可以写成 1.xxxxxx 的形式,其中xxxxxx表示小数部分。
IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分。比如保存1.01的时候,只保存01,等到读取的时候,再把第一位的1加上去。这样做的目的,是节省1位有效数字。以32位
浮点数为例,留给M只有23位,
将第一位的1舍去以后,等于可以保存24位有效数字。
至于指数E,情况就比较复杂。
首先,E为一个无符号整数(unsigned int)
这意味着,如果E为8位,它的取值范围为0-255;如果E为11位,它的取值范围为0~2047。但是,我们知道,科学计数法中的E是可以出现负数的,所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。比如,2^10的E是10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001。
然后,指数E从内存中取出还可以再分成三种情况:
E不全为0或不全为1
这时,浮点数就采用下面的规则表示,即指数E的计算值减去127(或1023),得到真实值,再将
有效数字M前加上第一位的1。
比如:
0.5(1/2)的二进制形式为0.1,由于规定正数部分必须为1,即将小数点右移1位,则为
1.0*2^(-1),其阶码为-1+127=126,表示为
01111110,而尾数1.0去掉整数部分为0,补齐0到23位00000000000000000000000,则其二进
制表示形式为:
E全为0
这时,浮点数的指数E等于1-127(或者1-1023)即为真实值,
有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于
0的很小的数字。
0 01111110 00000000000000000000000
E全为1
这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);
好了,关于浮点数的表示规则,就说到这里。

3.3引例解释

下面,让我们回到一开始的问题:为什么 0x00000009 还原成浮点数,就成了 0.000000 ?
首先,将 0x00000009 拆分,得到第一位符号位s=0,后面8位的指数 E=00000000 ,
最后23位的有效数字M=000 0000 0000 0000 0000 1001。

由于指数E全为0,所以符合上一节的第二种情况。因此,浮点数V就写成:
   V=(-1)^0 × 0.00000000000000000001001×2(-126)=1.001×2(-146)
显然,V是一个很小的接近于0的正数,所以用十进制小数表示就是0.000000。
再看例题的第二部分。
请问浮点数9.0,如何用二进制表示?还原成十进制又是多少?
首先,浮点数9.0等于二进制的1001.0,即1.001×2^3。
9.0 -> 1001.0 ->(-1)01.00123 -> s=0, M=1.001,E=3+127=130
那么,第一位的符号位s=0,有效数字M等于001后面再加20个0,凑满23位,指数E等于3+127=130,即10000010。
所以,写成二进制形式,应该是s+E+M,即
0 10000010 001 0000 0000 0000 0000 0000
这个32位的二进制数,还原成十进制,正是 1091567616 。

总结

学习c语言,不难接触到数据的存储,而掌握好这方面的知识需要我们进行多方面的深入了解,相信自己经过一段时间的沉淀后,能对这一部分有更深入的了解。

【每日总结】数据在内存中的存储相关推荐

  1. c语言字母是怎么存储,C语言之数据在内存中的存储

    C语言之数据在内存中的存储 在我们学习此之前,我们先来回忆一下C语言中都有哪些数据类型呢? 首先我们来看看C语言中的基本的内置类型: char //字符数据类型 short //短整型 int //整 ...

  2. C语言——深度剖析数据在内存中的存储

    大家好!我是保护小周ღ,本期为大家带来的是深度剖析数据在内存中的存储,不知道,大家学了这么久C语言,有没有想过一个问题,我们在程序设计中的数据是怎么在计算机中存储的?我们都知道 一个整型数据 int ...

  3. 【C语言】浮点型数据在内存中的存储方式

    目录 一. 前言 二. 问题的引出 三. 两类浮点型数据(float.double)在内存中的存储方式 3.1 两类浮点型数据的存储模型 3.1.1 浮点型数据数值读取的通用模型 3.1.2 floa ...

  4. JavaScript中数据在内存中的存储方式

    JavaScript中数据在内存中的存储方式 1.js数据类型分类 简单数据类型:Number.String.Boolean.Undefined.Null 复杂数据类型:Object.Array.Fu ...

  5. C语言—深度剖析数据在内存中的存储

    深度剖析数据在内存中的存储 数据类型介绍 类型的基本归类 整形在内存中的存储 大小端介绍 整形在内存中的存储的相关练习 浮点型在内存中的存储 浮点型在内存中的存储相关介绍 数据类型介绍 内置类型(C语 ...

  6. 【C语言】全面解析数据在内存中的存储

    文章目录 前言 类型的基本分类 整型 浮点数 自定义类型 整型在内存中的存储 原码.反码.补码 大端和小端 如何判断编译器是大端还是小端 浮点数在内存中的存储 总结 前言 C语言中有char.shor ...

  7. 带你深度剖析《数据在内存中的存储》——C语言

    文章目录 一.数据类型介绍 二.整型在内存中的存储方式 2.1 原码.反码.补码的讲解 2.2 大小端介绍 2.2.1 大小端的概念 2.2.2 为什么要区分大小端存储呢? 2.2.3 大小端判断练习 ...

  8. C语言中数据在内存中的存储

    要想了解数据在内存中的存储的话,首先应该了解数据的类型. 下面介绍C语言中数据类型: 1.C语言中的基本内置类型: char //字符数据类型 大小为1个字节 short //短整型 大小为2个字节 ...

  9. 数据存储---整形数据在内存中的存储

    我们每一次写代码的时候,都会创建变量.那么所创建的整形变量是如何在内存中存储的呢? 目录 1.数据类型介绍. 2.整形数据在内存中的存储形式. 3.大小端字节序的介绍. 1.数据类型介绍 本文重点介绍 ...

  10. c语言double数据存储形式,C语言 float、double数据在内存中的存储方式

    float在内存中占4个字节(32bit),32bit=符号位(1bit)+指数位(8bit)+底数位(23bit) 指数部分 指数位占8bit,可以表示数值的范围是0-(表示0~255一共256个数 ...

最新文章

  1. 压缩软件系统设计测试结果,空气压缩机测试系统软件设计与研究
  2. 微服务实战(七):从单体式架构迁移到微服务架构
  3. c语言中函数可以有几个参数,C中子函数最多有几个形参
  4. mysql-表记录之增删改操作
  5. jmeter模拟登陆
  6. 3904三极管是什么功能_什么是放大器。它有什么特性
  7. Input 输入设备驱动框架
  8. 聊聊Vue(前端Vue面试包过)【面试干货】
  9. java foreach break_Java8中的foreach跳出循环break/return
  10. 问题二十:C++全局debug “ray tracing图形”实例
  11. 使用邮件客户端整合日常信息
  12. JavaScript页面刷新的所有方法
  13. 顶尖、顶级、权威期刊目录
  14. 开启CPU虚拟化功能
  15. Redhat下小企鹅输入法的安装
  16. 为什么面向对象糟透了?
  17. SAP SD VA01 在销售范围中,订单类型XX没有定义
  18. 带有分销体系的开源知识付费系统——cremb
  19. One-Error多标签分类_多分类及多标签分类算法
  20. 医疗时鲜资讯:如何玩转医学影像中心?

热门文章

  1. 【程序人生】东哥脸盲认不清哪个是兄弟了!
  2. 用js获取QQ好友信息和QQ群信息
  3. 重点人员动态管控系统开发,公安合成作战平台建设
  4. kali实战:获取内网目标图片
  5. java音乐剪辑代码(只能剪辑从开始到最后的部分,也可以中间截取,加个计数器就行了)
  6. 新手小白,想做自媒体赚钱,要掌握这3个核心要素
  7. A - 卿学姐与公主(线段树+单点更新+区间极值)
  8. 潮人篮球不显示服务器,潮人篮球:一个老玩家对各个位置的一些看法
  9. 奢侈品电商?“寺库”可不是这么定义自己的
  10. 计算机基础(二):压缩算法