int类型的数据都是以补码形式存储的, 正数的原码、反码、补码相同,负数的补码等于原码先取反再+1
//-10的原码、反码、补码
//10000000000000000000000000001010 - 原码
//11111111111111111111111111110101 - 反码
//11111111 11111111 11111111 11110110 - 补码
//0xFF FF FF F6 - 16进制
//每4个bit位转化为一个16进制数,如最前面的1111,等于16,表示为16进制就是f
//最后面的0110等于2+4=6,表示为16进制就是6
//20
//00000000000000000000000000010100 - 原码
//00000000000000000000000000010100 - 反码
//00000000 00000000 00000000 00010100 - 补码
//0x00 00 00 14 -16进制
运算也是以补码形式进行,如-10+20,
//00000000 00000000 00000000 00010100 20的补码
//11111111 11111111 11111111 11110110 -10的补码
//两者相加
//11111111 11111111 11111111 11120210
//100000000 00000000 00000000 00001010 发生截断
//000000000 00000000 00000000 0001010 10的补码
数据的存储形式,有大端存储和小端存储
大小端字节序指的是数据在电脑上存储的字节顺序
大端字节序是把数据的高字节内容存放到低地址处,低字节内容存放在高地址处
小端字节序是把数据的高字节内容存放到高地址处,低字节内容存放在低地址处
设计一个程序,判断当前机器是大端存储还是小端存储
int main()
{
int a = 1;
char* p = (char*)&a;
//强制类型转换,0x00 00 00 01,取出的要么是00,要么是01
//故*p要么是1要么是0,如果是0,说明是按顺序放的,为大端存储,如果是1,说明是反过来放的,为小端存储
if (1 == *p)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}
//小端:返回1
//大端:返回0
可以函数调用把该代码升级一下:
int check_sys()
{
int a = 1;//0x00 00 00 01
char* p = (char*)&a;//取出a的地址,强制类型转换
return *p;//取出值,若为00则取出0,为01则取出1
}
int main()
{
int ret = check_sys();
if (ret == 1)
printf("小端\n");
else
printf("大端\n");
return 0;
}
再简化一下:
int check_sys()
{
int a = 1;
return *(char*)&a;
}
int main()
{
int ret = check_sys();
if (ret == 1)
printf("小端\n");
else
printf("大端\n");
return 0;
}
数据类型分类
整型家族:int、short、long、long long,字符在存储的时候,存储的是ASCII码值,ASCII是整数,故在归类的时候字符属于整型家族。
char分为unsigned char、signed char,short、int、long、long long也一样
char到底是signed char还是unsigned char是取决于编译器的,常见的编译器上char==signed char
浮点数家庭:float、 double
构造类型(自定义类型):数组类型(如int arr[10]和int arr[5],它们的类型就是将数组名去掉,即int [10]和int [5])、结构体类型struct、枚举类型enum、联合类型union
指针类型:int* pi、char* pc、float* pf、void* pv
空类型:void表示空类型(无类型),通常应用于函数的返回类型、函数的参数、指针类型
浮点数的存储规则:
(-1)^S * M * 2^E
(-1)^s表示符号位,当s=0,V为正数;当s=1,V为负数。
M表示有效数字,大于等于1,小于2。(换算成二进制的数字只有0/1所以1≤M<2)
2^E表示指数位。
例如数字5.5,分成小数点前和后
小数点前的5转化为二进制,为101
小数点后的5转化为二进制为1,现在转化为了101.1
由于1≤M<2,也就化为了1.011*2^2,由于是正数,所以s=0
故s=0,M=1.011,E=2。
对于M,我们隐藏小数点前的1,这样可以节省一位内存。
对于E,我们要加上127,避免出现负数。(注意,如果是64位的浮点数,则加1023)
当M不够填满这23位时,就需要在低位补零,补齐 23 位。
对于32位的浮点数,最高的1位是符号位s,接着的8位是指数E,剩下的23位为有效数字M。
对于64位的浮点数,最高的1位是符号位s,接着的11位是指数E,剩下的52位为有效数字M。
所以浮点数5.5存储在电脑中的是:
0 10000001 01100000000000000000000
转化为16进制:
0x40 b0 00 00
按小端存储,为0x00 00 b0 40
怎么取出浮点数?
分三种情况:E不全为0或者不全为1(1和0都有)、E全为0、E全为1
E不全为0或者不全为1
这时,E要减去127(64位减去1023),得到真实的E,再将M前加上第一位的1。如
0 10000001 01100000000000000000000
E为129,减去127,为2
011为小数部分,加上整数部分的1,为1.011
符号位为0,(-1)^0*1.011*2^2
即101.1,这是二进制数,最后将其转化为十进制,即为5.5
E全为0
浮点数的指数E等于1-127(或者1-1023),即为真实值,有效数字M不再加上第一位的1,而是还原为0.xxxxx的小数,这样做是为了表示±0,以及接近于0的很小的数字。
E全为1
这时如果有效数字M全为0,表示±无穷大