数据在内存中的存储是因不同的类型而不同的。
但首先我们需要知道的是,在C语言中,数据在内存中的存储是以变量的形式存储的。每个变量都有一个地址,指向内存中的特定位置。变量的值存储在这个地址对应的内存单元中。不同类型的变量在内存中占据不同大小的空间,例如整数型变量通常占据4个字节的空间,而字符型变量通常占据1个字节的空间。所以说实际上数据的存储也是由于类型所占字节不同而改变的。
接下来分别对不同类型的存储进行介绍。
整型
存放形式
存储由符号位和数值位两部分组成;
最高位也就是从左往右第一位就是符号位,用0表示正,用1表示负。
数值位就是除了符号位以外的其他位。
三种形式
而对于存放的形式有三种,原码、反码、补码
正整数的原、反、补码都相同。
负整数的三种表⽰⽅法各不相同。
原码:直接将数值按照正负数的形式翻译成⼆进制得到的就是原码。
反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。
补码:反码+1就得到补码。
我们知道,对于整型来说,数据存放的形式是补码。因为在计算机系统中,数值⼀律⽤补码来表⽰和存储。 这样可以表示正数、负数和零。在内存中,整型数据以二进制形式存储,可以直接进行算术运算和逻辑运算。
字节序
大小端(Endian)是指在存储多字节数据时,字节的存储顺序。
在内存中,从左往右,地址是从低向高的;而字节从左往右也是从低而高的,这时候就会出现两种存储顺序。
小端字节序
数据的高位字节存储在高地址,而低位字节存储在低地址(倒着存储)
大端字节序
数据的高位字节存储在低地址,而低位字节存储在高地址(正着存储)
根据小端字节序给出的例子,这里的地址应该就是
在C语言中,大小端的概念通常体现在处理底层数据存储和网络通信时。例如,当跨平台进行数据传输时,需要考虑不同平台的大小端存储方式,以确保数据能够正确解释和传递。
C语言提供了一些方法来处理大小端存储,例如可以使用联合体(union)或位操作来进行字节顺序的转换。另外,一些库函数也提供了处理大小端存储的功能,如htonl()和ntohl()函数,用于在网络通信中进行大端和小端之间的转换。
实际上就是由于寄存器或者某些硬件之间的差异导致了大小端字节序的区分。所以在不同平台之间需要根据它们各自的字节序来进行传输。
浮点型
在理解浮点型数据在内存中的存储之前,需要理解一个规则:IEEE 754_百度百科 (baidu.com)
简单来说,就是浮点型的存储遵循这么一个公式:
举例:
十进制的7.0-->二进制的111.0-->浮点型公式的(-1)^0*1.11*2^2
可以得出S=0,M=1.11(因为M是要大于等于1且小于2),E=2。
根据这个标准,浮点数通常使用32位或64位来表示,分别称为单精度浮点数和双精度浮点数。
单精度浮点数
使用32位来存储,其中包括1位符号位,8位指数位和23位尾数位。
双精度浮点数
使用64位来存储,其中包括1位符号位,11位指数位和52位尾数位。
M占用的bit位越多,数据精度越高。
E占用的bit位越多,数据范围越大。
而由于64位所占位数本身就更多,所以double类型也被更常使用、
对于E、M,还有一些特殊的规定。
E
⾸先,E为⼀个⽆符号整数(unsigned int) 这意味着,如果E为8位,它的取值范围为0~255;如果E为11位,它的取值范围为0~2047。但是,我们知道,科学计数法中的E是可以出现负数的,所以IEEE 754规定,存⼊内存时E的真实值必须再加上⼀个中间数;
对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。⽐如,2^10的E是10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001。
M
由于 1≤M<2 ,也就是说,M可以写成 1.xxxxxx 的形式,其中 xxxxxx 表⽰⼩数部分。这也可以说明,M的第一位数字永远都只可能是1,因此1可以被舍去,只保存后⾯的 xxxxxx部分。⽐如保存1.01的时候,只保存01,等到读取的时候,再把第⼀位的1加上去。这样做的⽬的,是节省1位有效数字。以32位浮点数为例,留给M只有23位,将第⼀位的1舍去以后,等于可以保存24位有效数字。
需要注意的是:浮点数采用二进制表示,而在二进制中有些小数是无法准确表示的,例如1/3这样的小数。因此,浮点数存储规则会导致一些小数在计算机内部以二进制形式存储时会产生舍入误差,使得浮点数在计算中可能会产生一些不精确的结果。所以我们得到的实际上是一个十分接近精确值的近似值。
字符型
字符型的数据在内存中存储的方式取决于编程语言和计算机体系结构。在C语言中,字符型数据被存储为ASCII码或Unicode编码的字符。每个字符占据一个字节的内存空间。
当我们声明一个字符型变量时,编译器会为这个变量分配一个字节的内存空间,并将字符的ASCII码或Unicode编码存储在这个内存单元中。例如,如果我们声明一个字符型变量char c = 'A';,那么字符'A'的ASCII码(65)将被存储在变量c的内存单元中。
在内存中,字符型数据的存储是以其ASCII码或Unicode编码的方式存储的,简单来讲就是计算机可以根据已有的ASCII码表等来直接识别我们存储的数据。当我们需要在程序中处理字符型数据时,可以直接访问这些内存单元来读取或修改字符的值。