数据存储分析

include//int cheak_sys(void)
//{
//	int a = 1;
//	char* p=(char *)&a;
//	return *p;
//}
//int main()
//{
//	int ret = cheak_sys();
//	if (ret == 1)
//		printf("小端");
//	else
//         printf("大端");
//     return 0;
//}

上次说到数据存储模式分大端输入和小端输入,这个代码就是用来测你的计算机是哪个端输入模式

思想是自定义一个检查函数,函数里面定义一个整型数字1,他有4个字节也就是32个二进制,补码等于源码是31个0与一个1,我们把它在内存中的地址取出来,强制类型转化

为(char*)指针,也就是把内存中低地址的一个字节八个二进制的地址取出来,对它进行解引用,如果是小端输入的话得到的值为1,就是小端模式,如果是0就是大端模式。

大端小端存储模式前面已经提过。

int main()
//{
//	char a =-1;
//	signed char b = -1;
//	unsigned char c = -1;
//	printf("a=%d,b=%d,c=%d\n", a, b, c);
//	printf("a=%u,b=%u,c=%u\n", a, b, c);
//	return 0;
//}

请问输出的应该是什么呢?

a=-1,b=-1,c=255

a=4294967295,b=4294967295,c=255

a是有符号字符型的数字,以%d形式就是有符号的十进制整型输出,首先整型提升,移动补码前面补符号位,补1结果还是-1的补码在转换为源码输出肯定是-1;

以%u形式就是无符号的十进制整型输出,首先整型提升是32个1,以%u输出默认为无符号数,补码等于源码就是2的32次方-1

b同理a所以结果一样

c定义位无符号的字符型是-1;先进行整型提升11111111前面补24个0,在以%d形式输出,源码就是补码就是2的8次方-1同理%也是一样

//int main()
//{
//	int i = -20;
//	unsigned int j = 10;
//	printf("%d", i + j);
//	//按补码进行计算,最后转化为有符号数
//	return 0;
//}

-20的源码是 10000000 00000000 00000000 00010100                      10的源码是 00000000 00000000 00000000 00001010   补码等于源码

-20的反码是 11111111 11111111 11111111 11101011                     -20的补码是 11111111 11111111 11111111 11101100 

                                                                                                          加起来结果是 11111111 11111111 11111111  11110110          

得到的补码减111111111 11111111 11111111 11110101   取反为  10000000 00000000 00000000 00001010这个为-10

int main()
//{
//	unsigned  int i;
//	for (i = 9; i >= 0; i--)
//	{
//		printf("haha\n");
//	}
//	return 0;
//}

                 这个的结果是什么呢?结果是一直死循环打印haha因为unsigned int 型范围是不可能小于零for循环结束不了

nt main()
//{
//	unsigned char i = 0;//i就不可能大于255
//	for (i = 0; i <= 255; i++)
//	{
//		printf("haha\n");
//	}
//	return 0;
//}

这个同理上个unsigned char范围是0-255它跳不出for循环,也是死循环打印

int main()
//{
//	char a[1000];
//		int i;
//	for (i = 0; i <= 1000; i++)
//	{
//		a[i] =-1-i;
//		//-1,-2,-3.......-128,127(-128-1),126,....1,0,-1   0的asiia码'\0'128+127
//	}
//	printf("%d", strlen(a));
//	return 0;
//}

首先定义了一个字符型数组,里面有1000个元素,给设了一个循环给数组初始化,下标是0的第一个元素是-1,依次是-2,-3,-128到了-128char的范围就是-128-127在减少一个数为127直到减到0,因为strlen是求'\0'前面元素的个数,0对应的正好是'\0',所以字符长度为128+127+255结果就是255

int main()
//{
//	int n = 9;
//	float* p = (float*)&n;
//	printf("n=%d\n", n);
//	printf("*p=%f\n", *p);
//	*p = 9.0;
//	//9.0
//	//1001.0
//	//(-1)^S+M*2^E
//	//(-1)^0+1.001*2^3
//	printf("n=%d\n", n);
//	printf("*p=%f\n", *p);
//	return 0;
//}

结果是什么呢?

n=9    *p=0.000000    n=1091567616        *p=9.000000

首先分析它是以整型9给存进去,在以%d形式拿出来打印打印的还是9

把n的地址强行转换为浮点型指针给了指针p,9在内存中补码为 00000000 00000000 00000000 00001001转换为浮点型认为它是一个浮点型的数字,以%f取出来的话,

最高位S为0表示正数,后8为为E都是0,有效数字M不在加上第一位的1,还原为0.xxxxxx的小数,E为-126默认是无限接近0的数字

就是(-1)^0*0.0000000 00000000 00001001*2^(-126)打印的是0.000000

然后给p指向的n赋值9.0 9.0写成(-1)^0*1.001*2^3 

S为0 E为130为 10000010  M为00100000000000000000000 所以最后为 0 10000010 00100000000000000000000以%d打印就是

以浮点型%f在拿出来还是9.00000000

这个题思想就是整型和浮点型在内存中的存放是不同的,整型形式存储以浮点型打印,以及以浮点型存储,整型拿出结果肯定不一样啊

  

整型和浮点型在内存中存储方式不一样。整型在内存中是以二进制补码存储的

规定,任意一个浮点数v都可以写成(-1)^S*M*2^E

(-1)^S表示符号位,当s=0时,v为正数,当s=1时,v为负数

M表示有效数字,大于等于1,小于2(M把1.xxxx改为0.xxxx只存小数位,默认有1,使得精度加1)

2^E表示指数位(E在内存中假如是4个字节加127,8个字节加1023)

float存储32个bit位 最高位S 后8位 E    最后23位 M

float存储64个bit位 最高位 S 后11位 E最后52位 M

浮点型数字从内存往出取,

M前面默认加1写成1.xxxxxx形式得到真实值

E假如不全为0或者1,根据多少字节减去127或者1023得到真实值

假如E全为0,有效数字M不在加上第一位的1,还原为0.xxxxxx的小数,E为-126默认是无限接近0的数字

E全为1,表示八个比特位都为11,E的真实值为128表示无穷大的数字。

////int main(void)
////{
////	float a = 1.0;//(-1)^0+0*2^0
////	float b = 9.0;
////	float d = 5.5;//(-1)^0+1.011*2^2 
////    double c = 1.0;//(-1)^0+0*2^0
////	return 0;
////}

里面把S,M,E拿出来不就知道在内存中存储了,注意M表示有效数字,大于等于1,小于2(M把1.xxxx改为0.xxxx只存小数位,默认有1,使得精度加1)取的时候得加1(E全为0,1除外),E根据多少字节加127还是1023往出取。

上一篇:8.24 贝壳面经


下一篇:js字节序