数据在内存中的存储

1. 整数在内存中的存储 :
整数的2进制表⽰⽅法有三种,即 原码、反码和补码
有符号的整数,三种表⽰⽅法均有符号位和数值位两部分,符号位都是⽤0表⽰“正”,⽤1表
⽰“负”,最⾼位的⼀位是被当做符号位,剩余的都是数值位。
正整数的原、反、补码都相同。
负整数的三种表⽰⽅法各不相同。
原码:直接将数值按照正负数的形式翻译成⼆进制得到的就是原码。
反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。
补码:反码+1就得到补码。
为什么数据在内存中是以二进制补码形式存放的呢?
在计算机系统中,数值⼀律⽤补码来表⽰和存储。
原因在于,使⽤补码,可以将符号位和数值域统⼀处理;
同时,加法和减法也可以统⼀处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是
相同的,不需要额外的硬件电路。
2.大小端字节序存储
⼤端(存储)模式:
是指数据的低位字节内容保存在内存的⾼地址处,⽽数据的⾼位字节内容,保存在内存的低地址处。
⼩端(存储)模式:
是指数据的低位字节内容保存在内存的低地址处,⽽数据的⾼位字节内容,保存在内存的⾼地址处
为什么会有⼤⼩端模式之分呢?
这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着⼀个字节,⼀个字节为8 bit 位,但是在C语⾔中除了8 bit 的 char 之外,还有16 bit 的 short 型,32 bit 的 long 型(要看
具体的编译器),另外,对于位数⼤于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度⼤ 于⼀个字节,那么必然存在着⼀个如何将多个字节安排的问题。因此就导致了⼤端存储模和⼩端存 储模式。
例如:⼀个 16bit short x ,在内存中的地址为 0x0010 x 的值为 0x1122 ,那么
0x11 为⾼字节, 0x22 为低字节。对于⼤端模式,就将 0x11 放在低地址中,即 0x0010 中,
0x22 放在⾼地址中,即 0x0011 中。⼩端模式,刚好相反。我们常⽤的 X86 结构是⼩端模式,⽽
KEIL C51 则为⼤端模式。很多的ARM,DSP都为⼩端模式。有些ARM处理器还可以由硬件来选择是 ⼤端模式还是⼩端模式。
练习:写一个程序判断当前机器是大端字节序还是小端字节序
这里要把a的地址转化为char*类型,这样才能保证解引用操作时一次访问一个字节。

接下来通过几道经典题目加深对本节知识的理解:

题目一:

本题目主要考察指针加减整数的运算以及大小端字节序存储的相关知识。

解析:a是数组名,数组名表示数组首元素的 地址(两种情况例外:sizeof(数组名),&数组名)

&表示取出整个数组的地址(类型是int(*)【4】)加一跳过整个数组(指针类型决定了+-整数的步长)再将数组指针变量强制转化为int*型,-1(ptr[-1]等价于*(ptr-1))跳过4个字节(一个整型)解引用得到4。

a是数组名,数组名表示数组首元素的 地址,将a(地址)强转为int类型再加1,在换算成整型指针(地址)

+1跳过了一个字节,再进行解引用操作访问4个字节,具体如下图所示:

由于是小端字节序存储,所以解引用操作后在内存中存储的00 00 00 02会被还原读取出来

因此得到20 00 00 00(16进制表示形式)

题目二:下图程序的运行结果是?

本题目答案为死循环。

解析:char类型数据的存储范围是-128~127

00000000————0

00000001————1

00000010————2

………………

01111111————127

10000000————直接翻译成-128

10000001————  -127(转换为源码再算)

11111111————    -1

unsigned char类型的数据存储范围为0~255————11111111(2^8-1)

11111111在加一变为100000000,unsigned char类型只能保留8个bit位,首位的一会丢失,所以i达到255后在加一又会回到0,循环往复。

因此i<=255是恒成立的,程序会陷入死循环。

题目三:下图程序的运行结果是?

由上图不难看出,程序陷入了死循环。

解析:unsigned int类型的数据存储范围为0~2^32-1,当i减为0时在减一i就会变成2^32-1,循环往复。因此本题目i>=0是恒成立的,所以会陷入死循环。(0-1=-1,32位全一,全是数值位)

题目四:

解析:strlen的任务是找到字符数组中的\0,返回\0之前的元素个数。

char类型的数据存储范围为-128~127

所以数组a的内容如下:

-1-2-3……-128127……3210000

因此本题结果为128+127=255.

题目五:

解析:%u打印无符号整数a是一个char型数据,128在内存中的存储形式为

00000000 00000000 00000000 10000000

char只保留一个字节  10000000

%u打印无符号整数,整形提升补符号位

11111111 11111111 11111111 10000000

由于%u打印无符号的整数,因此系统会认为上面的数字就是原码。转换成10进制就是4294967168

题目六:

本题目 -128

10000000 00000000 00000000 10000000————原码

11111111 11111111 11111111 01111111————反码

11111111 11111111 11111111 10000000————补码

char只保留一个字节  10000000

整型提升11111111 11111111 11111111 10000000

由于%u打印无符号的整数,因此系统会认为上面的数字就是原码。转换成10进制就是4294967168

题目七:

解析:

-1

10000000 00000000 00000000 00000001————原码

11111111 11111111 11111111 11111110————反码

11111111 11111111 11111111 11111111————补码

char只保留一个字节11111111

以%d形式打印,需要整形提升,补符号位

11111111 11111111 11111111 11111111

再翻译成原码,10000000 00000000 00000000 00000001,因此打印-1.

但由于c的类型是unsigned char,是无符号的,因此其在整形提升时补0

00000000 00000000 00000000 11111111

无符号整数的原反补相同,因此直接翻译255(2^8-1).

3.小数(浮点型数据)在内存中的存储

根据国际标准IEEE(电⽓和电⼦⼯程协会) 754,任意⼀个⼆进制浮点数V可以表⽰成下⾯的形式:
V = (−1)^  S M ∗ 2 ^ E
(−1)  ^ S 表⽰符号位,当S=0,V为正数;当S=1,V为负数
M 表⽰有效数字,M是⼤于等于1,⼩于2的
2 ^ E 表⽰指数位.
只要你愿意,任何一个浮点型的数据都可以使用上述方式表示
但是有一些浮点数注定是没有办法精确保存的。
比如3.14 无论小数点之后的二进制位怎么凑,都凑不出0.14
要想存储一个浮点型数据,只需要存住S E M就可以了。
比如 5.5 的二进制表示形式为101.1

即1.011*2^2.

S表示符号位 正数S为0.   M是有效数字即1.011   E表示指数位即2

要想存储5.5数据,只需要存住S 0   E2    M1.011就可以了。

IEEE 754规定:
对于32位的浮点数(float),最⾼的1位存储符号位S,接着的8位存储指数E,剩下的23位存储有效数字
M
对于64位的浮点数(double),最⾼的1位存储符号位S,接着的11位存储指数E,剩下的52位存储有效
数字M
比如float类型:5.5
第一位存S 接着八位存E 其余存M
E的存储:先将E加上127在转化为二进制存储。读取时系统会自动让其减127还原
M的存储:只存储小数点之后的位,读取的时候系统会自动补充小数点前的1还原
11000000101100000000000000000000
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。
对于E的存储,还存在一些特殊情况
接下来通过一道例题来巩固浮点数的存储方式
这道题的输出结果是:
9
0.000000
1091567616
9.000000
通过输出结果我们可以得出结论:
整型数据和浮点型数据在内存中的存储方式是不同的。
具体解析如下图:

完。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值