在冯诺依曼体系结构下.内存是非常重要的组成部分!
1.内存VS外存(硬盘,优盘,软盘等)
- 1.内存支持"随机访问能力": 也就是计算机访问内存上的某个地址的数据,花费时间开销都差不多,无论地址编号的大小,时间复杂度都为O(1);外存同样也支持随机访问能力,但是支持的程度远不及内存
- 2.内存量比较小,外存比较大
- 3.内存访问速度快.外存慢(速度快3-4个数量级,也就是几千倍)
- 4.内存的成本高,外存的低
- 5.掉电后,内存的数据丢失,外存的不会丢失(电脑睡眠未掉电,关机是掉电)
2.大小端字节序存储方式问题
int NNN = 9;
小端字节序: 数字的低位存储早内存的低地址上 (09 00 00 00 ) ----->简单记忆为: 小 小 小
大端字节序: 数字的低位存储在内存的高地址上 (00 00 00 09)
格列佛游记中小人国讨论的问题就是: 吃鸡蛋时候,是从大头开始磕,还是从小头开始磕鸡蛋. >> 这个问题类似于大小头磕鸡蛋的问题,大端字节序存储符合人的直觉,以后可以方便记忆:吃鸡蛋从大头开始磕
3.编写一个判断机器是否小端存储的函数:
int isLittleEnd(int* p) {
char* p2 = (char*)p;
if (*p2 == 0x44) {
return 1;
}
return 0;
}
4.原码,反码,补码这样设计的原因在于: 计算机硬件中实现减法器,乘法器,除法器成本高,只需要在软件中通过补码运算就能解决加减乘除
减法: 加负数
乘法: 多加n次自身
除法:多减n次自身
正数的原码,反码,补码是一样的!!!
负数的存在运算关系: 补码 = 反码 + 1 ;
原码 = 补码de反码 + 1;
反码 = 原码除符号位取反
5.常用的%d \ %u打印实质上是什么含义?
%d 表示的是: 打印一个有符号的 十进制的整数(int型32位)
要注意的一点是: char一个字节的变量, 当按照%d打印,会将char隐式转为int型打印,转换过程中,高位的三个字节填充符号位的值.
%u 表示的是: 打印一个无符号的 十进制的整数(int型32位)
同理.%u打印会把参数转为unsigned int类型,再进行打印
问题1: 以下代码的运行结果是: -1 -1 255
char a = -1;
signed char b = -1;
unsigned char c = -1;
printf( "a = %d, b = %d, c = %d", a, b, c);
char 型8位 -1 的补码是 1111 1111
int型32位 -1 的补码是 1111 1111 1111 1111 1111 1111 1111 1111
高位补的是符号位上的值,这是为了防止出现这样的转化过程中数据错误.
signed char 与 char 没有区别
unsigned char 在进行 %d打印时
1111 1111 高位补0(unsigned char 无符号位), 当做正数处理,补位按0补位.
则补位后结果是 0000 0000 0000 0000 0000 0000 1111 1111 ------> 255十进制数
结论: unsigned 类型变量比较坑, 容易在隐式转换等处发生问题, 能不用就不用unsigned.
问题2: 以下代码的运行结果是: 4,294,967,168
char a = -128;
printf("%u" , a);
思路: 把(char) a ---.> int----> unsigned int型打印
高位填充符号位 1000 0000
char ---> int \||/
1111 1111 1111 1111 1111 1111 1000 0000
int ---> unsigned int \||/
1111 1111 1111 1111 1111 1111 1000 0000 ||此时最高位不再是符号位, 不再表示负数,下面的数字就被理解为一个很大的正数4,294,967,168
问题3:以下代码的运行结果是:
char a = 128; // 128溢出 char 的范围是 -128 ---> +127
printf("%u \n", a);
128内存中二进制表示的是 0000 0000 0000 0000 0000 0000 1000 0000
char a = 128;发生截断,导致唯一的1变成了符号位,此时a的值本质为 -128;
\||/ 隐式转换为int
\||/ 转换为unsigned int 变成了很大的正数(回到问题2的过程中了)