首先在计算机中,整数有三种二进制表示方法:原码、反码和补码,而正数和复数的表示又有一定的不同:符号位都是用0来表示“正”,用1表示“负”,正数的原反补码都相同,而负数的表示方法如下:
原码
直接将数值按照正负数的形式翻译成二进制就可以得到原码。
反码
将原码的符号位不变,其他位依次按位取反就可以得到反码。
补码
反码
+1
就得到补码。
但是对于整形来说的话,在计算机系统中,数值一律用补码来表示和存储,这样子可以将符号位和数值域统一处理。例如:
0a 00 00 00刚好对应10的补码0000 0000 0000 0000 0000 0000 0000 1010
0 0 0 0 0 0 0 a
但是为什么是反方向存放的呢?这就不得不提计算机的两种存储方式:
大端字节序存储:
大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址
中;
小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位,,保存在内存的高地
址中。
由此可以看出在vs2022上是小端字节序存储。
我解释一下:首先我们假设
高字节 低字节
a=10=0x 00 00 00 0a
低地址 高地址
大端:00 00 00 0a
小端:0a 00 00 00
这样子应该很形象了吧
好,接下来我们来解析几段代码:
//1.
//输出什么?
int main()
{
char a = -1;
signed char b = -1;
unsigned char c = -1;
printf("a=%d,b=%d,c=%d", a, b, c);
return 0;
}
请问,这段代码的输出结果是啥?给你两分钟时间考虑。我就直接跳过了哈
能不能想到这个答案呀?首先给自己提出一个疑问,为什么呢?然后来分析这段代码
如果不太了解整形提升的话可以自己先去了解之后才来解析这段代码,明白了吗?如果没明白,好,继续再来一个例子:
//输出什么?
int main()
{
char a = -128;
printf("%u\n", a);
return 0;
}
这段代码的输出结果呢?老样子,两分钟时间考虑。我直接跳过了哈
哇,怎么会输出这么大的数字啊,你能想到吗?在不分析的情况下,我相信没人能想到这个结果吧
来继续分析:
dec就是十进制4294967168
看吧神奇吧 欧克经过这两段代码相信大家对数据存储有了一定自己的理解,那么整形存储结束了,浮点型呢?
来继续看例子:
int main()
{
int n = 9;
float* pFloat = (float*)&n;
printf("n的值为:%d\n", n);
printf("*pFloat的值为:%f\n", *pFloat);
*pFloat = 9.0;
printf("num的值为:%d\n", n);
printf("*pFloat的值为:%f\n", *pFloat);
return 0;
}
那这段代码的输出结果是啥呢,由于大部分人都没有学过浮点型数据的存储,那么我就直接运行了
哇!!!第一个和第四个可以理解,第二个和第三个是什么鬼?不要慌,分析开始:
我们先了解一下浮点数在计算机中的存储方式:
所有的浮点型数据都可以用下面的公式进行存储,
(-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
。
那么,按照上面
V
的格式,可以得出
S=0
,
M=1.01
,
E=2
。
十进制的
-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
IEEE 754
对有效数字
M
和指数
E
,还有一些特别规定。
前面说过,
1≤M<2
,也就是说,
M
可以写成
1.xxxxxx
的形式,其中
xxxxxx
表示小数部分。
IEEE 754
规定,在计算机内部保存
M
时,默认这个数的第一位总是
1
,因此可以被舍去,只保存后面的
xxxxxx
部分。比如保存
1.01
的时
候,只保存
01
,等到读取的时候,再把第一位的
1
加上去。这样做的目的,是节省
1
位有效数字。以
32
位
浮点数为例,留给
M
只有
23
位,
将第一位的
1
舍去以后,等于可以保存
24
位有效数字。
至于指数
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
。
关于详细的规定大家直接去查资料吧,我这里就不啰嗦了。
看结果也符合:
以上就是我对数据存储的全部理解,如有错误,敬请指正!!
谢谢各位读者!!!!