整形家族
类型 | 有符号数 | 无符号数 |
---|---|---|
char | signed char | unsigned char |
short | signed short[int] | unsigned short[int] |
int | signed int | unsigned int |
long | signed long[int] | unsigned long[int] |
int short long使用时都表示有符号数,而char使用时取决于编译器
大小端的概念
小端:数据的低位存放到内存的低地址处,数据的高位存放到内存的高地址处
大端:数据的低位存放到内存的高地址处,数据的高位存 放到内存的低地址处
因为存在多个字节在内存安排问题,所以引出了大小端概念
如何判断编译器是采用大端还是小端的呢?
int a = 1;
char *pa=(char *)&a;
if(*pa==1)
{
printf("小端");
}
else
{
printf("大端");
}
代码分析
//输出什么?
#include<stdio.h>
int main()
{
char a = -1;
signed char b=-1;
unsigned char c=-1;
printf("a=%d,b=%d,c=%d",a,b,c);
return 0;
}
-1的补码11111111 11111111 11111111 11111111
给到char会发生截断取低8个bit 11111111
有符号数整形提升补符号位,提升完打印结果使用的是原码
无符号数整形提升补0
所以a=-1,b=-1,c=255
include<stdio.h>
int main()
{
char a= -128;
printf("%u\n",a);
return 0;
}
-128补码11111111 11111111 11111111 10000000,截断给a->10000000,整形提升补符号位以无符号数输出结果为:4294967168
浮点数存储
浮点数家族分为float、double和long double
据国际标准IEEE(电气和电子工程协会)754,任意一个二进制浮点数V可以表示成下面的形式:
(-1)^S*M*2^E
(-1)^S表示符号位,当S=0,V为正数;当S=1,V为负数。
M表示有效数字,大于等于1,小于2。
2^E表示指数位。
列如:十进制5.5
S=(-1)^0
M=1.011
E=2^2
M:因为规定M一定是1开头所以在存储时,默认舍弃目的就是多出一位空间使数据更加的精确,比如1.011只存储011,当把存储数据读出时,再将第一位的1加上去
E:在存储时会将原E的值加上(127/1023)(若是float+127,double+1023)进行存储,E是无符号数,若是(8位)范围0~255,若是11位范围0~2047。
S:符号位
指数E从内存中取出还可以再分成三种情况:
1⃣️E不全为0或不全为1
这时,浮点数就采用下面的规则表示,即指数E的计算值减去127(或1023),得到真实值,再将 有效数字M前加上第一位的1。
2⃣️E全为0
这时,浮点数的指数E等于1-127(或者1-1023)即为真实值,
有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字。
3⃣️E全为1
这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);
代码分析
intmain()
{
int n = 9;
float* pFloat=(float*)&n;
printf("n的值为:%d\n",n);//9 毋庸置疑
printf("*pFloat的值为:%f\n",*pFloat);
//因为整形和浮点型存储不一样所以,存储二进制值是00000000 00000000 00000000 00001001
//对于整形看待是9(正数原反补一样)
//对于浮点数:(符号位)0(E)00000000 (M) 0000000 00000000 00001001
//因为E全为0,((-1)^0)*(2^-126)*0.000000 00000000 00001001约等于0
//所以输出0
*pFloat = 9.0;
//存储0 100000010 0010000000000000000000
//按照整数输出值为:1091567616
printf("num的值为:%d\n",n);
printf("*pFloat的值为:%f\n",*pFloat);//9.0浮点数存储,浮点数输出。
return 0;
}