整理不易,3连走起
1.整数的储存
★整数有3种形式,原码,反码,补码。整数在内存中是以二进制的补码形式保存的。有符号整数的最高位是符号位,0表示正,1表示负,其余位都是数值位。
★正整数的原反补相同。
★负数的原码是这个数的二进制。反码是除符号位,其他位按位取反。反码+1就是补码。同样的,负整数的反码除符号位之外其他位按位取反之后+1即为原码。
★例:-15的原反补转换
1.1整数的计算
★整数在内存中都是以二进制补码的形式储存的,计算也是计算的二进制补码。
★cpu只有加法器(加法的硬件电路),用补码进行运算可以统一处理符号位和数值位,不需要其他的硬件电路。
★乘除法的本质也是加法,比如3×4的本质是3+3+3+3。
★例:-9与5的和的计算
(统一处理了符号位)
2.浮点数的储存
★浮点数的保存方式是国际标准IEEE754(电子电气协会)定义的。
★浮点数在内存中会单独保存符号,有效数字,指数。
整数的二进制位表示的是2 ^0 , 2 ^1 , 2 ^2 , 2 ^3 , 2 ^4 , 2 ^5……
浮点数的小数部分各小数位分别是 2 ^-1, 2 ^-2, 2 ^-3, 2 ^-4……
即 0.5,0.25,0.125,0.0625,0.03125.……
★浮点数的表示公式:V = (-1)^ S × M × 2^E
S:正负号,0为正数,1为负数
M:(二进制)有效数字,1<M<2
2^E:指数(unsigned int)
★浮点数的储存规则
★ 例: float类型的 -5.875
-5.875是个负数——>所以最高位为1——>(-1)^S==-1,
S== 1;
-5.875的数值位用二进制表示为101.111(小数字部分为0.5+0.25+0.125),科学计数法表示为1.01111×2²(小数点左移两位)
对于32位float的浮点数的指数
E== 2+127==129——>1000 0001
M只保存小数点后的部分,即01111,后面补0
所以float类型(32位)的-5.875在内存中是这样保存的
1 10000001 01110000000000000000000
★浮点数的存取注意事项:
┅因为E有可能是负数,所以对于32位浮点数的E,在保存的时候,要加上127。对于64位浮点数的E要加上1023。
┅从内存中取E的时候,要根据浮点数的位数减去127或者1023。
┅另外,E为全1的时候,真实的E为255-127,这么大的指数,代表小数点左移了128位,即整数部分是二进制是2^128,我们定义这个浮点数位无穷大。反之E为全0的时候,表示无限小)
2.1浮点数与整数的转换问题
★将一个整数用浮点数的形式读出来,或者将一个浮点数用整数的形式读出来,都是直接读的对方的二进制位。
★例(以浮点数的形式读取整数):
#include<stdio.h>
int main()
{
int a = 1105461248; //0 10000011 11001000000000000000000
printf("%d\n", a); //E==131-127==4(表示小数点向左移动了4位)
float* p = (float*)& a; //M=11001(二进制科学计数法小数点后面的值)
printf("%f\n", *p); //科学计数法:1.11001×2^4
//即:11100.1 转换为十进制即为28.5
return 0;
}
★以上代码的运行结果
3.大小端字节序
★大小端字节序指的是数据在内存中的存储顺序。
★数据的低位存在高地址处还是低地址处?
★由于内存的地址分配单位是字节(8bit),所以对于2字节及以上的数据必须分字节存储
比如int类型的0000 0000 0000 1111 0000 0000 0000 0001
它的4个字节分别为00 0F 00 01 那么这4个字节都有对应的地址,不同的编译器会用不同的顺序存储。
★低位存在地地址处的是小端字节序
★低位存在高地址处的是大端字节序
★例:
★如何判断在当前编译器上的大小端字节序
★用程序表示1:
#include<stdio.h>
void test(int* a)
{
if (*(char*)a == 1)
{
printf("小端字节序");
}
else
{
printf("大端字节序");
}
}
int main()
{
int a = 1;
test(&a);
return 0;
}
★用联合体(共用体)/结构体的方式
#include<stdio.h>
union lty
{
int a;
struct ytl
{
char b;
char c;
char d;
char e;
}m;
}yy;
int main()
{
yy.a = 1;
if (yy.m.b == 1)
{
printf("小端字节序");
}
else
{
printf("大端字节序");
}
return 0;
}