每篇一句:
可以不光芒万丈,但不能停止发光
一、整形在内存中存储
1、 整形介绍
char
unsigned char
signed char
short
unsigned short [int]
signed short [int]
int
unsigned int
signed int
long
unsigned long [int]
signed long [int]
还要知道整形各自在内存中占有大小来加以判断,依次排序是1、2、4、4(8)个字节。有了一些了解可以判断不同类型整形所占有空间大小。但在计算机识别数据时,也只知道1,0。
2、原码、反码、补码
这里便解决了这个问题,原码、反码、补码这些都是1、0变换来表示其他数字大小以及存储。在整数中又可以分为正反俩类,这里便有了符号之分1为负,0为正。
原码:根据数值大小直接写出二进制位,最高位为符号位。
反码:符号位不变,其余按位取反。
补码:在反码基础上进行加一。
还有一个规律就是正数原码、反码,补码值相同而负数需要遵守以上规则进行变化,可以使用一个简单代码进行验证
#include<stdio.h>
int main()
{
int i = 10;
//原码 00000000000000000000000000001010
int j = -10;
//原码 10000000000000000000000000001010
//反码 11111111111111111111111111110101
//补码 11111111111111111111111111110110
printf("%d\n", i);
printf("%d", j);
return 0;
}
可以清楚看见整形数据存储时是以反码形式进行的,但是这里还会发现一个问题,按照注释来解释这里数据存储顺序问题。
int i = 10;
//原码 00000000000000000000000000001010
这里存储顺序应该是
00 00 00 0a
但是经过我们查看后发现顺序与我们想法相反。这里就不得不说到字节存储顺序·
3、大小端
什么是大端小端:
大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址 中;
小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位,,保存在内存的高地 址中。
关于这个大小端还有一个故事;在乔纳森·斯威夫特的著名讽刺小说《格列夫游记》中,小人国内部分裂成Big-endian和Little-endian两派,区别在于一派要求从鸡蛋的大头把鸡蛋打破,另一派要求从鸡蛋的小头把鸡蛋打破。斯威夫特借以讽刺英国的政党之争,在计算机工业中指数据储存顺序的分歧。
这个便可以解释我们上面顺序问题。这里我们还可以写一个代码进行模拟实现大小端判断;
#include <stdio.h>
int check_sys()
{
int i = 1;
return (*(char *)&i);//强制类型转换,比较第一个字节
}
int main()
{
int ret = check_sys();
if(ret == 1)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}
这里有强制类型转换,我们知道是int 类型转换为char类型。根据上面介绍这俩类型转换其实在大小方面有所区别。转换实质就是截断或者进行整形提升
整形提升:其实是小于整形的类型经过高位的补0,或1。从而达到与整形int相同字节数。
这里不同类型进行补位时,高位数据也有所不同。比如
unsigned char
无符型补0,有符号补符号位。
signed char
下面代码进行验证
int main()
{
char a = 0xb6;
short b = 0xb600;
int c = 0xb6000000;
if (a == 0xb6)
printf("a");
if (b == 0xb600)
printf("b");
if (c == 0xb6000000)
printf("c");
return 0;
}
二、浮点型
1、 认识浮点型
float
double
long double
既然分出来浮点型和整形就说明它们各自有不同的存储形式。浮点型有俩种float(4字节)、double(8字节)类型,我们知道的就是精度不同。但是很多时候我们就只知其然而不知其所以然。
2、存储方式
通过以下代码进行探索
int main()
{
int n = 7;
float* pF= (float*)&n;
printf("n的值为:%d\n", n);
printf("*pFloat的值为:%f\n", *pF);
*pF = 7.0;
printf("num的值为:%d\n", n);
printf("*pFloat的值为:%f\n", *pF);
return 0;
}
如果我们只是看代码而不进行编译,可能在看见运行结果时有一点点出入,这里和我们进行整形数据时规律不同。这里有一个** IEEE745标准**,对于浮点型数据有了一定规范。
(-1)^S * M * 2^E
(-1)^S表示符号位,当S=0,V为正数;当S=1,V为负数。
M表示有效数字,大于等于1,小于2。
2^E表示指数位。
在标准规定下对于内存调用,各自占有大小进行规定。
通过对别这里我们进度问题便可以得知double精度为什么高于float。也可以解释上面代码运行结果。