数据在内存中的存储<C语言>

杨树与晨光 2024-06-23 12:35:18 阅读 93

导言

        在计算机中不同类型的数据在计算机内部存储形式各不相同,弄懂各种数据在计算机内部存储形式是有必要的,C语言的学习不能浮于表面,更要锻炼我们的“内功”,将来在写程序的时候遇见各种稀奇古怪的bug时,也便能迎刃而解,所以本文将着重介绍,整数在内存中的存储、大小端字节序和判断、浮点数的存储。


整数在内存中的存储

       这部分的内容在前面已经讲过,现在让我们来复习一下:

一个数的二进制表示方法有三种:原码、反码、补码

        原码:直接将数转为2进制序列,得到的就是原码

        反码:符号位不变,将其它位取反

        补码:在反码基础上+1

在C语言中整数可分为有符号整数和无符号整数

        有符号整数:有符号位(第一位),0为正、1为负

        有符号整数:没有符号位,即全为正数。

在计算机内部存放的是补码,为啥是补码?

        因为CPU只有加法器,在计算机内部,正数的补码是本身,负数补码符号位不变,其他位取反,存放补码可实现加减法的统一运算(不需要添加减法器):

//在计算机内部存放的是补码,为啥是补码?int main() {int a = 9;//a的补码:00000000 00000000 00000000 00001001int b = 4;//b的补码:00000000 00000000 00000000 00000100int c = a - b;//c=a-b会被转化为c=a+(-b)// a的补码:00000000 00000000 00000000 00001001//-b的补码:11111111 11111111 11111111 11111100// c的补码 100000000 00000000 00000000 00000101//相加结果多出一位,int型只有4字节、32位,高位抛弃// c的补码: 00000000 00000000 00000000 00000101//正数原反补相同,10进制数为5printf("%d", c);return 0;}

运行结果:


 大小端字节序和判断

        超过一个字节的数据在存储时就会有存储顺序的问题:

         通过调试观察一个整型在内存中的存储可知:a的低位存储在低地址处,当前平台属于小端存储模式。

大端存储模式:

        是指数据的低位字节存储在内存空间的高位地址处。(大对大)

小端存储模式:

        是指数据的低位字节存储在内存空间的低位地址处。(小对小)

为了更好的理解下面给出几道练习:

        练习1(百度笔试10分)

简述大端字节序和小端字节序的概念,设计一个程序来判断当前机器的字节序。

        

         练习2

以下代码输出结果是啥?

#include <stdio.h>//X86环境 ⼩端字节序 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;}

运行结果:

 分析一下:

#include <stdio.h>//X86环境 ⼩端字节序 int main(){int a[4] = { 1, 2, 3, 4 };int* ptr1 = (int*)(&a + 1); //&a取出整个整个数组的地址(访问权限为4*sizeof(int)个字节),再加1到元素4的后面int* ptr2 = (int*)((int)a + 1); //(int)a:将地址转为int类型的数,并加1,就是加了一个字节 //因为当前平台为小端字节序,加1跳过了01,并从第二个字节开始00 00 00 02printf("%x,%x", ptr1[-1], *ptr2); //ptr[-1],访问权限为int型,倒退4字节,来到4的起始地址并打印 //*ptr2:00 00 00 02,因为平台为小端字节序,所以该数为2000000return 0;}

浮点数的存储

        浮点数的存储是比较特殊的,因为它具有小数位,如果采用整数存储方法肯定是不行的,于是IEEE(国际电气和电子工程协会)754规定,任意一个浮点数V可以表示为下面这种形式:

●-1的S次方:符号位,S为1时负数,S为0时正数

●M:有效数字,M大于1小于2

●E:指数位

如10进制数5.5转为二进制数101.1

那么S=1

        M=1.011

        E=2

浮点数在存储时就是存储的SME,值得注意的是,常见浮点数float和double型的字节长度是不一样的,那么在存储时,SME的内存分配会有所不同:

注意点:

●前⾯说过, 1≤M,也就是说,M可以写成 1.xxxxxx 的形式,其中 xxxxxx 表⽰⼩数部分。 因此1.可以舍去。

●指数E,E为一个无符号整数,为了能存负数,754规定:存入内存时E的真实值必须再加上一个中间数,float:127,double:1023

举例:

#include <stdio.h>int main(){int n = 9;//小端字节序:00001001 00000000 00000000 00000000float* pFloat = (float*)&n;//转为float,但是存储的数据没有发生变化,依旧是00001001 00000000 00000000 00000000printf("n的值为:%d\n", n);//9printf("*pFloat的值为:%f\n", *pFloat);//0.000000//以%f的形式打印,那么会把这个数据float的方式读取,也就是SEM的形式//0 0001001 000000000000000000000000=1.0*2的(9-127)次方,无限接近于0*pFloat = 9.0;//以浮点数存储也就是0 10000010 00100000000000000000000printf("num的值为:%d\n", n);//将0 10000010 00100000000000000000000以整数形式读取也就是1,091,567,616printf("*pFloat的值为:%f\n", *pFloat);//9.000000return 0;}

运行结果:

 值得注意的是在浮点数存储的时候,E有几种特殊情况:

●E全为0时,还原成2进制数时,还要减去中间数,那么这个值就会无限的小(并且M不会加上省略的1),接近于0,超出数据表示范围

●E全为1时,还原成2进制数时,255减去中间数,指数E为255,那么这个值就会无限的大,超出数据表示范围



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。