数据在内存中的存储形式

数据的基本类型

一 整形数据

char字符数据类型,在内存中占一个字节
short短整型,在内存中占两个字节
int整形,在16位的平台中占两个字节,在32位平台中占四个字节
long长整型,在32位平台中占四个字节,在64位平台中占八个字节
long long更长的整型,占八个字节
float单精度浮点型,占四个字节
double双精度浮点型,占八个字节

         一个变量的创建是需要在内存中开辟空间的,而空间的大小是根据不同的类型来决定的。数据在这些空间中以二进制补码的形式存储,而计算机中有符号数有原码,反码,补码三种表示形式,并且还有符号位和数值位,符号位用0表示正数,1表示负数

      数值位正数和负数的表示方式则不同。

//表示数字20
原码:   0000 0000 0000 0000 0000 0000 0001 0100
16进制:0x 0     0    0    0    0    0    1    4
0x00 00 00 14

//表示数字-10
原码:     0000 0000 0000 0000 0000 0000 0000 1010
反码:     1111 1111 1111 1111 1111 1111 1111 0101
补码:     1111 1111 1111 1111 1111 1111 1111 0110
16进制:0x   f    f    f    f    f    f    f    6
0xff ff ff f6

-10在内存中存储的二进制数就是1111 1111 1111 1111 1111 1111 1111 0110

如果一个数是正数,那么在内存中,他的原码,反码和补码是一样的,但是如果这个数是负数,他会以补码的形式进行存储。

int main()
{
	int a = 20;
	int b = -10;
	int* p = &a;
	int* q = &b;
	return 0;
}

                    《数据在内存中的存储形式》                                       《数据在内存中的存储形式》

在这组数据中,会发现数据的存储顺序是倒着的。

这是因为大端和小端这两种存储模式

      大端:是数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中。低地址–>>高数据   例如:手机

      小端:是指数据的地位保存在内存的低地址中,数据的高位则保存在内存的高地址中。低地址–>>低数据    例如:电脑

判断计算机是大端还是小端:

union uu//联合结构体
{
	int i;
	char a;
};//特点:i和a共用一块内存
int CheakSys()
{
	union uu un;
	un.i = 20;
	return un.a;
}
int main()
{
	int ret = CheakSys();
	if (ret == 0x14)
	{
		printf("小端\n");
	}
	else
	{
		printf("大端\n");
	}
	return 0;
}

《数据在内存中的存储形式》

对二进制的新理解

#include<stdio.h>
#include<Windows.h>
int main()
{
	unsigned int i;//i是无符号类型
	for (i = 9; i >= 0; i--)
	{
		Sleep(100);
		printf("%u\n", i);
	}
	return 0;
}

 

#include<stdio.h>
int main()
{
	unsigned char i = 0;//i是无符号char类型
	for (i = 0; i < 256; i++)
	{
		printf("hello word\n");
	}
	return 0;
}

      经过运行可以看到,两个程序都陷入了死循环,这是因为二进制数据存放的原因,它们可以近似的看成一个环形,以有符号数来说,char类型的范围为-128 ~ 127,就形成了从0-127- -128- -1 -0这样的一个环,所以,i永远不会等于128,就会造成死循环,类似于钟表的一个结构《数据在内存中的存储形式》

127   0111 1111 
1     0000 0001

127+1   1000 0000 (-128的原码)
 反码   1111 1111
 补码 1 0000 0000

 

-1 原码 1000 0001
   反码 1111 1110
   补码 1111 1111
 
1  原码 0000 0001

-1+1 1 0000 0000  (0的原码)

 数据的整形截断和整形提升问题

       不同的数据类型所表示的数据存储范围都有差异,当给一个变量输入一个超出改类型最大存储范围的数时,再对这个变量进行打印,结果则会出现差异,就像下面这两个例子一样:

int main()
{
    char a = -128;
    printf("%u\n",a);
    return 0;
}

int main()
{
    char a = 128;
    printf("%u\n",a);
    return 0;
}
-128 在内存中的存储是 
10000000 00000000 00000000 10000000-->这是他的原码
11111111 11111111 11111111 01111111-->这是他的反码
11111111 11111111 11111111 10000000-->这是他的补码

        char 类型只占一个子节大小,所以在给a初始化赋值后,就只能把-128后8位赋值给a,因为电脑是小端,低地址存放低数据,所以a的补码是 1000 0000  ,这里就发生了整形的截断,下面打印a 的时候,%u 是以32位无符号数打印,就会在a的高位上补1(关于补位,如果是无符号数,就补0;如果是有符号数,就补他的符号位的数字),所以最终打印的

a

11111111 11111111 11111111 10000000 --->4294967168   

这就发生了整形的提升。

二  浮点型在内存中的存储

int main()
{
	int n = 9;
	//0000 0000 0000 0000 0000 0000 0000 1001

	float *pFloat = (float *)&n;
	printf("n的值为:%d\n",n);//9
	printf("*pFloat的值为:%f\n",*pFloat);//0.000000
	//以浮点类型视角去读数据
	//0 00000000 00000000000000000001001

	*pFloat = 9.0;
	//1001.0->1.001*2^3
	//0 10000010 00100000000000000000000

	printf("num的值为:%d\n",n)
	//1091567616 整形的视角去读取数据

	printf("*pFloat的值为:%f\n",*pFloat);//9.0
	return 0;
}

出现这种情况是因为,国际标准IEEE(电气和电子工程)754,规定任意一个浮点数V可以写成下面的形式         

 

(-1)^S*M*2^E

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

      M表示有效数字,大于等于1,小于2。

      2^E表示指数位。

       规定:对于32位的浮点数,最高一位是符号位S,下来是8位指数E,最后是23位有效数字M(注意:因为有效数字本身就是小数位的,所以在出现位数不够的情况下,应该在后面补零      相当于0.11100000000,如果在前面补零,就会成为0.0000011111,使得原来的数变小)

十进制:5.0
二进制:101.0  相当于1.01*2^2
       
        (-1)^S*M*2^E
         S=0   M=1.01   E=2

    而在实际中,对于指数E位,如果E是八位,它的取值范围是0~255,如果E是11位,它的取值范围是0~2047,为了防止在计数过程中出现负数的情况,IEEE 754规定:存入内存时,E的真实值必须加一个中间数,对于8位的E,中间数是127,对于11位的E,中间数是1023.    

2^10
E=10
保存成32位浮点数的时候,保存的数据是  10+127=137 -->1000 1001

E全为0  ---->  表示无限接近于0    浮点数里没有绝对的0
E全为1  ---->  表示正负无穷大

             

    原文作者:_ 菜 -∞
    原文地址: https://blog.csdn.net/duchenlong/article/details/101539348
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞