深入了解C语言中数据的存储

mac2026-02-09  9

C语言是贴着计算机运行的一种语言 相对于其他语言我们更需要了解C语言中不同的数据都是怎么存储的。

深度剖析的话 可将其分为四个方向 1. 数据类型介绍 2. 整形在内存中的存储:原码、反码、补码 3. 大小端字节序介绍及判断 4. 浮点型在内存中的存储解析

我们从第一个开始来逐个进行解读

1. 数据类型介绍

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

对数据类型的进行一个基本归类 我们可以将其分为以下五组 整形家族: 浮点数家族: 构造类型: 指针类型 空类型: void 表示空类型(无类型) 通常应用于函数的返回类型、函数的参数、指针类型。

2. 整形在内存中的存储

我们知道变量的创建是要在内存中开辟空间的。空间的大小是根据不同的类型而决定的。 我们要知道这些空间计算即是如何开辟的?计算机又是如何将数据存储起来的? 我么先来了解这几个概念 计算机中的有符号数有三种表示方法,即原码、反码和补码。 三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位 三种表示方法各不相同。 原码 直接将二进制按照正负数的形式翻译成二进制就可以。 反码 将原码的符号位不变,其他位依次按位取反就可以得到了。 补码 反码加1就能得到原码的补码 正数的原、反、补码都相同。

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

3.大小端介绍

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

一道判断大小端的题目

#include <stdio.h> int check_sys() { int i = 1; return (*(char *)&i); } int main() { int ret = check_sys(); if (ret == 1) { printf("小端\n"); } else { printf("大端\n"); } return 0; } //代码2 int check_sys() { union { int i; char c; }un; un.i = 1; return un.c; }

这道判断大小端的题目巧妙地运用了C语言的隐式类型转换是字节的截断和提升 从计算即大小端存储差异入手 从而巧妙地进行解答

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

我们曾经学习过的浮点数包括: float、double、long double 类型。 但是浮点数与整形在计算机中的存储却大不相同 我们来看一段代码

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

运行结果如图 解读: 根据国际标准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。

因此对于计算机来说也得按照这种方法进行存储 对于32位的浮点数,最高的1位是符号位s,接着的8位是指数E,剩下的23位为有效数字M。 对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M。

特别规定. 1≤M<2 M可以写成 1.xxxxxx 的形 式,其中xxxxxx表示小数部分。 IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分。 指数E 首先,E为一个无符号整数 所以IEEE 754规定,存入内存时E的真 实值必须再加上一个中间数,对于8位的E,这个中间数是127

我们经过简单了解现在再对上面的题进行一个合理的解释 对于前两个printf 首先 int n=9; 然后我们将n的地址取出来存入了一个指针变量中 我们知道 地址在内存中一般是占四个字节的 int的变量在内存中也是占四个字节进行存储的 注意 float*是一个浮点型的指针 int位整型变量 我们将整形取地址然后强转成一个float的地址进行存储 显然当我们进行读取时候 会出现错误 n=9的二进制 00000000 00000000 00000000 00001001 当转成float时 因为 float数据分三部分进行存储 对于 00000000 00000000 00000000 00001001 将该数据看作浮点数的话 是一个很小的数据 (-1)^0 * 10 ^0 *1.0000000…… 此处省略 因此打印出来的结果就是一个0.000000 (float数据打印时小数点后跟默认六位)

然后对后面两个printf进行分析 我们在打印前首先对pfloat的值进行了一个改变 --9.0 因此 n的地址的值就发生了改变 同样的pfloat的值也发生了改变 *pfloat打印出来的值是9.000000 很容易理解 n的值打印出来是一个奇怪的数字 9 的二进制表示 00000000 00000000 00000000 00001001 按照上述规则 9.0内存中存储 0 10000010 001 0000 00000000 00000000 我们将其转化为十进制发现正好是 1091567616

最新回复(0)