目录
1.各种数据类型
我们在以往的学习中已经学过许多种内置类型:char、short、int、long、longlong、float、double……
然而在C语言中还有许多基本的数据类型:struct、int*、float*……
接下来我们对其中进行简单的分类:
整形类型:
char
unsigned char
signed char
short
unsigned short [int]
signed short [int]
int
unsigned int
signed int
long
unsigned long [int]
signed long [int]
浮点型类型:
float
double
构造类型:
> 数组类型 arr【】
> 结构体类型 struct
> 枚举类型 enum
> 联合类型 union
指针类型:
int *pi;
char *pc;
float* pf;
void* pv;
空类型
viod表示空类型(无类型),通常应用在函数的返回类型、函数的参数、指针类型等等,应用也十分广泛。
接下来我们重点了解本篇博客的重点:整形、浮点型数据在内存中的存储方式
2.整形数据是如何存储的
2.1原码、反码、补码
首先我们应该知道,计算机中整数有三种表示方式:原码、反码、补码。
原码
直接将十进制数转化为二进制数的形式。
反码
将原码的符号位不变,其他位按位取反得到
补码
反码+1得到补码
而在内存中,整数数据的存储都是以补码的方式存储的。
而正数的原、反、补码都相同,负数的原、反、补码各不相同。
3.浮点型数据是如何存储的
3.1浮点型数据的存储规定
浮点型数据的数据的存储是具有规则的,与整数数据的截然不同,所以,为了了解浮点数的存储规则,我们要来了解IEEE754的规定:
任何一个二进制的浮点数V可以表示成以下形式:
(-1) ^S * M *2^E
(-1)^S表示符号位,S为0表示正数,S为1表示负数。
M表示有效数字,大于等于1,小于等于2
2^E 表示指数位
在内存的存储中,只存储S、M、E3种格式:
对应float(单精度)类型:
对应double(双精度)类型:
接下来举几个例子:
十进制的5.5,对应的二进制:101.1。
改为以上的表示形式:(-1)^0 * 1.011 * 2^3
其中S=0,M=1.011,E=3;
这便是十进制下5.5的表示形式;
其中M的处理为:将小数点移动,移动小数点直到M在1-2的范围中,而E可以理解为小数点的移动位数。S则就是正数是0,负数是1。
这样才能保证(-1)^0 * 1.011 * 2^3的结果等于101.1。
3.2浮点型数据在内存中的存储
了解了浮点数的存储规则,那浮点数是如何存储到内存中的呢?这里,IEEE协会又做出了一些规定。
M
因为M属于[1,2)之间,可以写成1.xxxxxx的形式,其中1是肯定存在的,所以M存储到内存中,总是保留小数点以后的部分xxxxxxxxx,这样可以存储更多的位数。
E
首先E是一个无符号整形(unsigned int)
所以E的取值范围是0-255之间(float)或0-2047(double)。
而在我们实际的使用过程中,E肯定是会出现负数的,比如我们要存储0.5(十进制),
0.5-->0.1(二进制)-->(-1)^1.0*2^(-1) [IEEE]-->这里小数点向右移动了1位,所以要乘上2*-1,才能表示二进制下的0.1,这时E就为-1了,而E是无符号整形,这是不允许的。
所以IEEE 754规定,E在存入内存时要加上一个中间值,即127(float)或1023(double)。所以上面的例子中,E=-1,所以在存到内存中,E=-1+127=126,再转为二进制,则存为0111,1111。
则例子0.5在内存中的存储形
3.3浮点型数据的取出
对于取出浮点数,只需要将S、M、E读出,然后相乘,就可以读出这个浮点型数据。
M的取出:
因为存入时,M的地方只保存了M小数点的后几位,所以在拿出是将M的值加上1.0,即可得到真实的M的值。
而E的取出中存在以下三种情况:
当E不全为0或不全为1
因为存进去时,E的值加上了中间值,所以在取出时,E的值就为内存中存储的数再减去127(1023),这样得到了E的真实值。比如上面的例子中0.5在内存中的存储形式:
当E为全0这时,浮点数的指数E等于1-127(或者1-1023)即为真实值。这样真实的E就表示为-126,即乘以2*(-126),这就表示了一个无限接近于0的数。
这时有效数字M也不再加上第一位的1,而是还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字当E为全1
这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s)。
4.大小端存储
4.1什么是大小端存储:
大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;
小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位,,保存在内存的高地址中。
4.2为什么会有大小端模式之分呢?
这是因为在计算机系统中,我们是以字节为单位的,每个地址单元
都对应着一个字节,一个字节为8bit。但是在C语言中除了8 bit的char之外,还有16 bit的short型,32 bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题。因此就
导致了大端存储模式和小端存储模式
4.3检测当前编译器是存储方式
那如何检测当前的编译器使用的大端存储还是小端存储呢?这里我们就可以写出一个程序来判断:
如果检测是1则就为大端存储,0则为小端存储。
//代码1
#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;
}
本篇文章的内容就到此结束了,看到这的留个赞呗~~