CMU-15213(计算机操作系统总结) - 第一章(整数类型)
事实1: Int(整数类型)不是整数, Float(浮点数)也不是自然数
例子:
?
当 是Int类型:
我们可以通过代码来验证一下
#include <stdio.h>
int main()
{
int x;
x = 40000;
printf("%d * %d -> %d\n", x, x, x*x);
x = 50000;
printf("%d * %d -> %d\n", x, x, x*x);
return 0;
}
40000 * 40000 -> 1600000000
50000 * 50000 -> -1794967296
我们不难发现打印出的结果是,不仅算错,而且还是一个负数,这是为什么呢?这就需要介绍Int类型在计算机系统里是如何表示的了。
讨论
在多数电脑中,Int被定义为4 bytes也就是32bits
类型 | 32bits环境下 | 64bits环境下 |
char | 1 byte | 1 byte |
short | 2 bytes | 2 bytes |
int | 4 bytes | 4 bytes |
long | 4 bytes | 8 bytes |
那么用32bits我们可以怎么来表达一个整数呢?这里要介绍的一种是绝大多数系统采用的表达整数的方式
二进制补码(two's complement):
公式:
例子:
其实举个简单的例子就是
第4位 | 第3位 | 第2位 | 第1位 | 第0位 |
-16 | 8 | 4 | 2 | 1 |
0 | 1 | 0 | 1 | 0 |
在了解了二进制补码之后,我们就可以算出在int类型有32bits并且使用二进制补码的情况下,int类型最大可以表示多少呢?
32bits | 二进制 | 十进制 |
INT_MAX(整数最大值) | 01111111 11111111 11111111 11111111 | 2,147,483,647 |
INT_MIN(整数最小值) | 10000000 00000000 00000000 00000000 | -2,147,483,648 |
我们可以很简单的证明正确性,既然第一位bit代表,其他bits都是代表正数,所以如果其他位置上有为1的bit那么这个值必然比INT_MIN要大,所以INT_MIN是int类型可以表示的最小值。同理也可以说明INT_MAX是int可以表示的最大值。
知识点:
INT_MIN的绝对值是INT_MAX+1
回到问题本身
了解了int类型可以表示的最大值,我们不难发现
50000乘50000导致了存储结果的int类型变量溢出。但是为什么结果是-1794967296这么一个奇怪的负数呢?
十进制 | -1794967296 | 50000 |
二进制 | 10010101 00000010 11111001 00000000 | 00000000 00000000 11000011 01010000 |
十进制 | 50000*50000=2500000000 |
二进制 | 00000000 00000000 11000011 01010000 × 00000000 00000000 11000011 01010000 0 10010101 00000010 11111001 00000000 |
我们可以看到32bits的无法表示2,500,000,000这个结果,导致被忽略,所以正确答案应该是
事实2:
你需要了解汇编语言,虽然我们大概率不会自己写汇编语言,但是我们需要了解他是如何构成的。
事实3: RAM(Random Access Memory)是个Unphysical Abstraction
- Memory referencing bugs especially pernicious
- Effects are distant in both time and space
- Memory is not unbounded
- It must be allocated and managed
- Many applications are memory dominated
- Memory performance is not uniform
- Cache and virtual memory effects can greatly affect program performance
- Adapting program to characteristics of memory system can lead to major speed improvements
比如c和c++没有任何内存保护机制,所以他会出现
- 数组越界
- 无效指针
- 错误的malloc()和free()
这种错误往往很难debug,比如数组很有可能在大多数情况都不会越界,但是因为程序员没有考虑到一些情况而导致数组越界,导致程序崩溃,无效指针和错误的malloc()和free()也会导致类似的错误。