源码,反码,补码的转化
首先我们要知道,一个字节有8个比特位。
对于正数而言他的三种码都是一样的
而对于负数来说
补充:short和char类似,这俩都分为short;signed short;unsigned short.
short = signed short = signed short [int].
大小端存储
大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;
小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位,,保存在内存的高地址中。
检测大端还是小端的代码:
int main()
{
int i = 1;
char p = (char)i;//因为如果int转换成char会存在截断的问题.
if (p == 1)
{
printf("小端");
}
if (p == 0)
{
printf("大端");
}
system("pause");
return 0;
}
//方法2
union un {
int i;
char c;
};
int main()
{
union un u;
u.i = 1;
printf("%d", u.c);
system("pause");
return 0;
}
例题1:
char a= -1;
signed char b=-1;
unsigned char c=-1;
printf("a=%d,b=%d,c=%d",a,b,c);
return 0;
思路:有符号的char存储先源码,最后转化成补码存储.所以
源码:10000001;反码:11111110;补码:11111111.又因为以%d输出(有符号的整形)所以又要从补码变回源码,又是-1.
而无符号的char直接把源码当做补码:10000001存储,所以以%d输出的时候,又会把10000001当做补码转换成源码,10000000,11111111.所以结果为255.
截断:发生在大转小
提升:发生在小转大;符号位为1补1,符号位为0补0;
例题2:
char a = -128;
printf("%u\n",a);
return 0;
思路:截断
0x 10000000 00000000 00000000 10000000
0x 11111111 11111111 11111111 01111111
0x 11111111 11111111 11111111 10000000
a截断->10000000
然后%u是无符号的所以直接输出
例题3
char a = 128;
printf("%u\n",a);
return 0;
思路:同理2,结果一样.都是一个比较大的值
例4:
unsigned int i;
for (i = 9; i >= 0; i--)
{
printf("%u\n", i);
}
分析:
当运行到i=-1
但由于i是无符号数,所以最高位不表示符号位,最高位也是数值位即(2^32-1)大于0,陷入死循环
例5:
unsigned char i = 0;
for (i = 0; i <= 255; i++)
{
puts("hello world!\n");
}
unsigned char 取值范围为0 -255,无论如何i的值都在0 - 255之间,所以会陷入死循环
浮点型在内存中的存储
切记浮点数在内存中的存储是不同于整形的!
规则:
比如十进制的5.0,二进制就是0101.0 就可以写成(-1)^ 0 * 1.01 * 2 ^ 2
在比如十进制的-5.0,二进制就是-0101.0 就可以写成(-1)^ 1 * 1.01 * 2 ^ 2
而规定float类型有一个符号位(S),有8个指数位(E),和23个有效数字位(M)
double类型有一个符号位(S),有11个指数位(E),和52个有效数字位(M)
E在存储的时候都是正数,又因为E是8比特位,和char类似,所以为了保证他在存寄进去的时候一定是正的,要给E加127(在取的时候再减127就好了).
例:
int main()
{
int n = 9;
float *pFloat = (float *)&n;
printf("n的值为:%d\n",n);
printf("*pFloat的值为:%f\n",*pFloat);
*pFloat = 9.0;
printf("num的值为:%d\n",n);
printf("*pFloat的值为:%f\n",*pFloat);
以整形存以整形取,或者以浮点存以浮点取都不会发生错误。但是如果整形和浮点型的类型就会出现变化
首先解释第一个。因为9是以整形存储以浮点数输出。相当于浮点数的提取。
整形的9在内存中以补码存储的(正数三码相同)。9——>0000 0000 0000 00001001
,而在提取的时候对于E还分为三种情况:
E不全为0,不全为1:
这时就用正常的计算规则,E的真实值就是E的字面值减去127(中间值),M的值要加上最前面的省去的1。
E全为0
这时指数E等于1-127为真实值,M不在加上舍去的1,而是还原为0.xxxxxxxx小数。这样为了表示0,和一些很小的整数。
E全为1
M全为0时,表示±无穷大(取决于符号位),M不全为1时,表示这数不是一个数
此时E为全0,所以符合第二种,M不加1,E在提取的时候减去127.
所以v=(-1)^0 * 0.0000000000001001 * 2^(-127)这是一个很小的数,所以相当于0.
接下的解释第二种。9以浮点数的形式存储。所以9.0=1001.0
所以s=0,E=3+127=130,M=1.001
浮点数9.0在内存中的二进制位:0 10000010 001 00000000000000000
(130的二进制位10000010,补在E位置,M为1.001,把最前面的1去掉,剩下0.001放在M位置),此时把这个二进制以补码的形式拿出来就是一个很大的值。