内存函数
1. 整数在内存中的存储
(1)旧识回顾:
之前在学到操作符的时候,我们就学过了下面的内容:
整数的二进制的表示方式有三种,原码、反码、补码
有符号的整数,三种表示方式均有符号位和数值位两部分,其中符号位是用"0"
表示正,用"1"
表示负,其他的都是数值位。
正整数的原、反、补码的表示方式都一样。
负整数的三种表示方式不同。
原码:直接将数值按照正负数的形式翻译成⼆进制得到的就是原码。
反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。
补码:反码+1就得到补码。
对于整形来说:数据存放内存中其实存放的是二进制的补码。
为什么呢:
在计算机系统中,数值⼀律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统⼀处理;同时,加法和减法也可以统⼀处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是
相同的,不需要额外的硬件电路。
(2)大小端字节序和字节序判断
首先我们来了解什么是大小端字节序
大端(存储)模式:
是指数据的低位字节内容保存在内存的高地址处,而数据的高位字节内容,保存在内存的低地址处。
小端(存储)模式:
是指数据的低位字节内容保存在内存的低地址处,而数据的高位字节内容,保存在内存的高地址处。
上述概念需要记住,方便分辨大小端。
练习1
请编写一个程序判断当前系统是大端还是小端(百度笔试题)
思路: 可以给定一个变量a为1,如果是小端的话读取一个字节的话得到1,如果是大端的话就得到0
配着下图方便理解:
代码实现:
练习2
请判断下面这串代码的输出结果:
解读:
注意这里因为给定的abc均为char
类型的,但是%d是要打印整数的,所以这里就会发生整形提升
练习3
判断下面代码的输出结果:
解读;
练习4
判断下面代码的输出结果:
错误思路:
正确思路;
正是由于char类型是有取值范围的,并且这还是个轮回,也就是说这里的a在取到-128时,这时候再往后就是127,然后再从127到0,当遇到\0
时strlen计算出255
练习5
请判断下列代码输出结果:
运行结果;
解读:因为这里的unsigned char 的取值范围为 0~255 ,导致for循环中的i<=255
恒成立,就导致了死循环。
练习6
请判断下面代码的输出结果:
运行结果:
解读: 因为unsigned int 的取值范围为 0 ~ 42亿+,所以for循环中的i>=0恒成立,也导致了死循环。
练习7
请计算下面代码的输出结果;
下面我们通过一个图示来理解:
这里&a取出的是整个数组,然后加一跳过的是整个数组的长度,然后就到了数组的最后,这时候被强转为int*
类型,ptr[-1]
代表*(ptr-1)
所以这里指针向左移动一个字节就指向了04的位置这个时候解引用访问一个整形,这时候再转化回去就是4,
但注意ptr2这里的a是强转为了int类型,然后加一就是一个字节所以这里的ptr2指向的是00的位置,然后被赋给int*类型的ptr2,这时候解引用就是访问一个整形,就得到了2000000
代码运行结果:
2. 浮点数在内存中的存储
引言
常见的浮点数:3.14159、1E10等,浮点数家族包括: float、double、long double 类型。
(1)浮点数的存储
根据规定浮点数存储满足以下规则
举例1:
举例2:
这里注意在小数点右面的位数就是2分之一的n次方,依次向后增长,这其实也就导致了浮点数的存储是有局限性的,它在存储一些特殊值的时候精度是会受到限制的
比如在存储3.14的时候,它是只能无限接近这个数,但是不能准确的表示出来
(2)浮点数存的过程
比如0.1
这里就出现了E为负数的情况,但是存放E的位置又只能存放正整数,所以这时候就需要将E的数值进行一个调整
(3)浮点数取的过程
- 常规情况:E不全为1不全为0
这时,浮点数就采用下面的规则表示,即指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第⼀位的1
比如:0.5的⼆进制形式为0.1,由于规定正数部分必须为1,即将小数点右移1位,则为1.0*2^(-1),其阶码为-1+127(中间值)=126,表示为01111110,而尾数1.0去掉整数部分为0,补齐0到23位
00000000000000000000000,则其⼆进制表示形式为:
0 01111110 00000000000000000000000
- E全为0
这时,浮点数的指数E等于1-127(或者1-1023)即为真实值,有效数字M不再加上第⼀位的1,而是还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字
0 00000000 00100000000000000000000
- E全为1
这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s)
0 11111111 00010000000000000000000
(4)例题
代码运行结果:
首先当我们看到这个结果的时候肯定挺出乎意料的,那么为什么会是这个结果呢,下面我们来分析一下
这个时候打印出的第二个结果几乎就是0
如上图所示,这时候以整数形式打印出来的结果就是上图下面这个二进制的十进制
最后以浮点数形式打印*pFloat自然就是上面这个结果,没什么好解释的。
总结
这期我们主要学习了整数和浮点数在内存中的存储,并且这其中也包括了之前学到过的整形提升,以及没有学过的大小端字节序