导言
在计算机中不同类型的数据在计算机内部存储形式各不相同,弄懂各种数据在计算机内部存储形式是有必要的,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