目录
:
使用这个类型开辟内存空间额度大小,决定了使用范围
数据在内存中占用的空间的大小时根据不同的数据类型而决定的
类型的基本归类:
1.整型家族
char : unsigned char ; signed char
short:unsigned short ;signed short
int :unsigned int ;signed int
long :unsigned long ;signed long
2.浮点数家族
float
double
long double
3.构造类型(自定义类型)
数组类型
结构体类型 struct
枚举类型 enum
联合类型 union
4.指针类型
int* pi;
char* pc;
float*pf;
void* pv;
5.空类型
void 表示空类型(无类型)
一、整型在内存中的存储
整数的二进制有三种表示形式:原码、反码、补码
其中,正整数 的原码、反码、补码 是相同的;而负整数的原码、反码、补码之间是需要进行一定的计算的;0的原码、补码和反码均为全0.
举例介绍(32位):
#include<stdio.h>
int main()
{
int a = 10;
//原码:00000000 00000000 00000000 00001010
//反码:00000000 00000000 00000000 00001010
//补码:00000000 00000000 00000000 00001010
// 将补码转为16进制 0000000A
int b = -10;
//原码:10000000 00000000 00000000 00001010
//反码:11111111 11111111 11111111 11110101
//补码:11111111 11111111 11111111 11110110
// 将补码转为16进制 FFFFFFF6
return 0;
}
需要注意的是:二进制中,首位为符号位,正整数时符号位为0,负整数时符号位为1。
故关于负整数三码转换可以总结为:
原码 -> 反码 : 除符号位外,其他位按位取反
反码 -> 补码 : 在反码的基础上+1
补码 -> 原码 : 除符号位外,其他位取反,然后+1
在计算机中存储时,数值一路使用补码进行存储和表示,有如下几点优点 :
1.使用补码,可以将符号位和数值域统一处理
2.加法和减法也可以统一进行处理(CPU只有加法器)
3.补码和原码相互转换,运算过程相同,不需要增加额外的硬件电路
接下来了解一下字节序:
字节序指字节在电脑中存放时的序列与输入(输出)时的序列,分为大端字节序和小端字节序
1.大端字节序:数据的低位字节序存放在高地址处,高位字节序存放在低地址处
2.小端字节序:数据的低位字节序存放在低地址处,高位字节序存放在高地址处
在vs2022中,采用的是小端字节序,所以在内存中监视上方的代码,可看到以下结果:
四位二进制转换为一位16进制,32位二进制即为8位十六进制,8位为一个字节,即两位16进制,小端字节序即如上图所示。
二、浮点型在内存中的存储
浮点数和整数在内存中的存储过程,是不一样的!!!
C语言中的浮点数在计算机内部的表示方法为:
任意二进制浮点数(假设V)可以表示为以下形式:
V = (-1)^S * M * 2^E
(-1)^S 表示符号位,当S = 0时,V为正数;当S = 1时,V为负数
M表示有效数字,大于等于1 且 小于2
2^E表示指数位
举例来说:十进制的-5.0,二进制为-101.0,相当于 -1.01*2^2。则S=1,M=1.01,E=2。
IEEE 754规定:
对于32位的浮点数,最高的1位是符号位S,接着的8位是指数E,剩下的23位为有效数字M。
对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M。
还有一些特别的规定。
表示有效数字的M,大于等于1且小于2.,即可以写为1.xxxxxxx的形式,在计算机内保存时,默认第一位总是1,因此可以被社区,只保存小数点后部分,如保存1.01时,只保存01,读取时再将第一位的1加上,这样可以节省1位有效数字。
指数E的情况就比较多。
E作为无符号整数,为8位时,取值范围是0~255,11位时,取值范围就是0~2047。但科学计数法中是可以出现负数的,所以,E的真实值必须由E减去中间数,8位的E减去127;11位的E,减去了1023。
E还有三种情况:
(1)E不全为0或不全为1。这时,浮点数就采用上面的规则表示,即指数E的计算值减去127(或1023),得到真实 值,再将有效数字M前加上第一位的1。
(2)E全为0。这时,浮点数的指数E等于1-127(或者1-1023),有效数字M不再加上第一位的1,而是还原为 0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字。
(3)E全为1。这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);如果有效数字M不全为0,表示 这个数不是一个数(NaN)。
还有一点是:整数和浮点数,在内存中的存取方式是不一样的!!!
#include<stdio.h>
int main()
{
// 整数和浮点数 在内存中的存取方式是不一样的
int n = 9; // 4 byte
float* pFloat = (float*)&n;
printf("%d\n", n); // 9
// *pFloat 是以浮点数的视角去看的
// 00000000 00000000 00000000 00001001 十进制 9
// 0 00000000 00000000000000000001001 浮点数的视角
// s E M
// 0.00000000000000000001001 * 2^-126
// 输出小数点后6位 -- 即 0.000000
printf("%f\n", *pFloat); // 0.000000
*pFloat = 9.0; // 以浮点数的视角存储 9.0
// 1001.0 二进制 9.0
// 1.001 * 2^3 E = 3
// 0 10000010 00100000000000000000000
// 0100 0001 0001 0000 0000 0000 0000 0000 转换十进制即为 1091567616
printf("%d\n", n); // 1091567616
printf("%f\n", *pFloat); // 9.000000
return 0;
}