【C语言】C语言成长之路之数据在内存中的存储ヽ(゚▽゚)ノ

❤️前言

好久不见大家,今天是新的一年的开端,小狮子在这里向大家问好,也希望大家在新的一年里能够开开心心,万事如意!

今天为大家带来的是一篇关于数据在内存中存储的博客,希望大家能够喜欢,温故知新,每天都有所收获😋

数据类型的一些基本介绍

整数类型

char 类型:
unsigned char
signed char

int 类型:
unsigned int
signed int

unsigned short int
signed short int
unsigned long int
signed long int

short和long 是用于修饰int 类型的前缀,因此也归到int中。

浮点数类型

单精度浮点型:float
双精度浮点型:double

构造类型

各种数组类型 (元素类型 数组名[ ])
结构体类型 struct
枚举类型 enum
联合体类型 union

指针类型

int*
char*
float*
......
指针类型也就是其他类型的变量与* 组合产生的类型,用于区分解引用时的访问权限大小和变化时的幅度大小。

这里要特别拎出来的是void* 所表示的空指针类型,它能保存地址的值,但是却不能直接解引用,这是因为系统无法知道该读取多少字节的空间,由此我们经常将它与 强制类型转换 (类型) 配合使用。

(📖传送门)如果大家想要仔细地了解指针类型的相关知识,可以看看我之前写的博客:

【C语言】C语言成长之路之万字长篇进阶指针——C指针的提升与总结,指针就该这样学|•‘-‘•) ✧_MO_lion的博客

空类型

void 表示空类型(无类型)
它通常被应用于函数的返回类型、函数的参数、指针类型。

整型在内存中的存储

原码、反码、补码

计算机中的整数有三种二进制表示方法,即原码、反码和补码。

我们知道,只要是整数在内存中以二进制补码形式存储,那么我们现在来复习一遍原码、反码、补码的相关知识。

原码:原码由需要表达的数字直接转化为二进制数字,若该数字为有符号数则第一个位为符号位,
其中 ,符号位为1 代表负数、0代表正数。
反码:由原码的符号位不变,其他位按位取反取得
补码:反码加一得到

对于正数,原反补码都相同;对于负数,原码补码需要运用转换规则进行转换。原码补码之间的转换可以直接由其中一者的二进制位符号位不变,其他位按位取反后加一得到。

大小端字节序

大端字节序存储:将数据的较低位数保存在内存的高地址内存中,而数据的较高位数,则保存在内存的低地址内存中。

小端字节序存储:与大端字节序存储相反,将数据的较低位保存在内存的低地址内存中,而数据的较高位数,则保存在内存的高地址内存中。

为什么会有大小端模式之分呢?

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

浮点型数在内存中的存储

引例

#include <stdio.h>
int main()
{
    int n = 9;
    float* pFloat = (float*)&n;
    printf("n的值为:%d\n", n);//1
    printf("*pFloat的值为:%f\n", *pFloat);//2

    *pFloat = 9.0;//用浮点数指针将浮点数9.0赋值给那一段内存空间
    printf("num的值为:%d\n", n);//3
    printf("*pFloat的值为:%f\n", *pFloat);//4
    return 0;
}

让我们一起看看这段代码的输出结果:

怎么样?这段代码的结果你想到了吗?那么我们现在继续来聊为什么会是这样的结果。

首先,我们要知道printf函数在以%d%f打印时分别是以十进制整数和浮点数的视角来观察对应数据的。

浮点数的存储规则

接着我们应该理解浮点数在内存中是如何存储的。

根据国际标准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 位的浮点数,S与单精度相同,而E和M则更大了不少,以此表达更大的精度。

其中值得一提的是,由于1<M<2,M的整数部分总是1,所以我们就把整数1省略,只留下小数部分存储在M对应的内存中。

那么现在我们就可以思考前面的例题了,1 和 4 对应的输出很好理解,打印时我们都是以对应的视角去看,自然在打印时输出对应的数值9。2和3则分别是将整数9以浮点数形式打印和将内存中的浮点数9.0以整数形式打印,2:E为全0则可以看作一个趋于零的浮点数;3:前面的E中有1,则在以整数视角来打印它时表示一个很大的数。

🍀结语

作为博客的作者,小狮子我很高兴大家能看到这里,希望看到这篇文章的你在这一整天都有好的心情,看完这篇文章之后也能有所收获!😊

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

发呆的yui~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值