c中数据的存储

c语言类型

1.内置类型
char
short
int
long
float
double

内置类型又可以分为整形家族和浮点数家族
整形家族:

char

unsigned char
signed char

short

unsigned short [int] int可写可不写,下同
signed short [int] int可写可不写

int

unsigned int
signed int

long

unsigned long [int]
signed long [int]

浮点数家族:

float
double

2.自定义类型(构造类型)

数组类型
结构体类型 struct
枚举类型 enum
联合类型 union

指针类型

int*
char*
void*

空类型

void

char在内存中的存储

char的大小是八位一个字节
那么写成二进制,8位二进制能表达的数字范围是00000000~11111111
在这里插入图片描述
所以,有符号的char的范围是: -128~127,而且可以看到,127再加个1,直接会变成-128
在这里插入图片描述

无符号char由于没有符号位,范围就是上图从头算到尾,即0~255

unsigned char和char相加,顺序:两个数的补码相加,加完后等到也是补码,打印的时候是结果转换为原码打印

浮点型在内存中的存储

整形在内存中存储的是二进制的补码,但浮点数不同,
根据国际标准IEEE754标准,任意一个二进制浮点数V可以表示成下面的形式:

(-1)^S * M *2^E
(-1)^S表示符号位,当s=0,V为正数,当S=1时,V为负数
M表示有效数字,大于等于1,小于2
2^E表示指数位

例:
9.0
1001.0
(-1)^0 * 1.001 * 2^3
S =0
M =1.001
E = 3
IEEE 754规定:对于32位的浮点数,最高的一位是符号位,接着的8位是指数E,剩下的23为有效数字M
在这里插入图片描述
对于64位的浮点数,最高位的符号位S,接着11位是指数E,剩下的52位为有效数字M
在这里插入图片描述
IEEE754标准对有效数字M的规定:1<=M<2,也就是说,M永远是1.xxxxxxx的形式,xxxxxx是小数部分,IEEE754标准规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分,比如保存1.01的时候,只保存01,等到读取的时候,再把第一位的1加上去,这样做的目的,是节省一位有效数字,以32位浮点数为例,留给M的只有23位,将第一位的1舍去以后,等于可以保存24位有效数字。

IEEE754对于指数E的规定:首先,E位一个无符号整数(unsigned int)这意味着,如果E为8位,它的取值范围为0~255;如果E为11位,它的取值范围为0 ~2047,但是,指数E是科学计数法中的次数,是可以为负数的,所以IEEE754规定,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127,对于11位的E,这个中间数是1023,比如,2^10的E是10,所以保存成32位浮点数时,比如保存成10+127=137,即10001001
举例:
5.5
101.1->二进制形式
-(1)^0 1.0112e2
S = 0
M = 1.011,省略开头的1,只保存011
E = 2,加中间值,float加127,所以是129
0 10000001 01100000000000000000000
S------E-------M,由于写完011后,后面还要20位,补0
转换成16进制
0x 40b00000
内存小端存储,高地址放高位,低地址放低位
所以在内存中是00 00 b0 40

存入浮点数数据我们已经清楚,指数E从内存中取出还可以再分成三种情况:
1.E不为全0或全1
取出时,指数E要减去127(或1023),等到真实值,然后再将M加上第一位的1
2.E为全0
这时,浮点数的指数E等于-127,(或者-1023),这样算出来的数超级小,几乎不会在现实中用到,所以此时算E就直接等于1-127(或者1-1023),算M时不再加上第一位的1,而是还原为0.xxxxxx,这样做是为了表示±0,以及接近于0的很小的数字
3.E全为1
1.xxx*2255直接就是无穷大或无穷小的数,不参与讨论
代码示例:

int main()
{
	int n=9;
	//int类型二进制
	//00000000 00000000 00000000 00001001 -补码
	float *pFloat = (float *)&n;
	//float指针把强制类型转换的int变量存入,由于都是4个字节,所以就地址来说,取出的地址部分是没问题的
	printf("n的值为:%d\n",n);//正常打印整形变量
	printf("*pFloat的值为:%f\n",*pFloat);
	//这里就出现了问题
	//float看待32位的二进制数的方式和int形不同,上面的32位int型在float眼中是这样保存的
	//0 00000000 00000000000000000001001
	//S    E                 M
	//因为E是全零,32位浮点数换算成实际值
	//(-1)^0 * 00000000000000000001001 * 2^-126
	//这数就相当于0,所以*pFloat的值就是0.000000



	*pFloat = 9.0//一开始就用浮点数形式保存
	// 1001.0
	//1.001*2^3
	//(-1)^0*1.001*2^3
	//二进制形式 E要加127,M要把0省掉,后面补0补到23位
	//0 10000010 00100000000000000000000
	printf("n的值为:%d\n",n);
	//从整形int角度看,第一个零是符号位,原码就是补码,
	//上面的32位就直接按照位数求出2的次方,最后结果是十进制的1091567616
	printf("*pFloat的值为:%f\n",*pFloat);//正常打印9.0
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值