介绍
c=[100.0,-100.0,-0.5,10.25] ;idl代码,表示float型的array
allen@xps:~$ od -x sample
0000000 0000 42c8 0000 c2c8 0000 bf00 0000 4124
0000020
也就是说float数组在内存中是这个样子
0000 42c8 0000 c2c8 0000 bf00 0000 4124
100
->0000 42c8
-100
->0000 c2c8
注意我们应该把上面的16进制数倒过来看,也就是
42c8 0000
=0100 0010 1100 1000 0000 0000 0000 0000
=0 10000101 10010000000000000000000
=
+(1.1001)2×2128+4+1−127=(1100100)2=100
c2c8 0000
=1100 0010 1100 1000 0000 0000 0000 0000
=1 10000101 10010000000000000000000
=
−(1.1001)2×2128+4+1−127=(1100100)2=−100
可见只有符号位改变了
所以,原码/反码/补码的概念只适用于整形!
但是上面怎么倒过来了,,内存中本来就是这样的吗?
还有,用hexedit
打开的话,是这个样子:
00 00 C8 42 00 00 C8 C2 00 00 00 BF 00 00 24 41
什么鬼?
再试了一下用Sublime TextEdit 3
打开,也是和hexedit
打开一样(这应该是内存中真正的样子)
0000 c842 0000 c8c2 0000 00bf 0000 2441
但如果按照
这种读法的话,应该这样看
42c8 0000 c2c8 0000 bf00 0000 4124 0000
当一个文件中包含了int型
#include <stdio.h>
int main()
{
unsigned int a[]={0,1,2,3};
int b[]={0,1,2,3};
int c[]={0,-1,-2,-3};
int d[]={131072,262144,524288,524288*2}; //2^17, 2^18 and so on
FILE *file;
file=fopen("/home/allen/sample_int","w");
fwrite(a,sizeof(unsigned int),4,file);
fwrite(b,sizeof(int),4,file);
fwrite(c,sizeof(int),4,file);
fwrite(d,sizeof(int),4,file);
fclose(file);
return 0;
}
subl 打开
0000 0000 0100 0000 0200 0000 0300 0000
0000 0000 0100 0000 0200 0000 0300 0000
0000 0000 ffff ffff feff ffff fdff ffff
0000 0200 0000 0400 0000 0800 0000 1000
仍然,按照我们认知的习惯,需要这样读,例如-2
:
IEEE 754
标准下是11111111 11111111 11111111 11111110
即ffff fffe
,
倒转2次得到feff ffff
再如2^17=131072
IEEE 754
标准下是00000000 00000010 00000000 00000000
即0002 0000
,
倒转2次得到0000 0200
或许用数字表示更清楚:
事实上上面的表示方法是十六进制的表示方法,也就是说上面的
12345678
实际上是
{12}{34}{56}{78}
四个字节,我们用
ABCD
来表示, 则上面的反转公式就可以简单地表示为:
看到这里应该明白了,其实内存中储存的就是课本上所教的补码(整形)和
IEEE 756
定义的浮点型,为什么反过来储存呢,这是系统决定的,即采用
Little Endian
或
Big Endian
(这个没求证过,我以前只知道
Little/Big Endian
会决定一个字节
bit
之间顺序上的储存方式,现在看来好像也会决定字节之间顺序上的储存关系)
同时要注意到单个
byte
在显示的时候并没有翻转过来,也就是可以两个数字``两个数字
地读这样说来,一开始使用的
od -x
命令其实是帮住用户把连续的两个字节倒过来,但感觉这没必要啊,并不是所有的类型都是两个字节表示的(如果真是这样确实是方便了)。难道是为了方便用户四个数字``四个数字
地读?
再来拿double
练习一下:
上面的C代码中在合适的位置加入
double e[]={1.0,3.0,100,-100};
fwrite(e,sizeof(double),4,file);
输出的文件中增加了这样两行
0000 0000 0000 f03f 0000 0000 0000 0840
0000 0000 0000 5940 0000 0000 0000 59c0
有了前面的结论直接阅读之:
- 取前面8个字节,并反转之得到
3ff0 0000 0000 0000
- 变成二进制
0011 1111 1111 {0000}x13
- 变成
IEEE 754
的double
格式0 01111111111 {0}x52
变成十进制数字 +1.0×2210−1−1023=1 , 完成,正确
取最后8个字节,
c059 0000 0000 0000
1100 0000 0101 1001 {0000}x12
1 10000000101 1001{0}x48
- −1.1001×220+22+210−1023=−(1100100)2=−(4+32+64)=−100 ,完成,正确