CMU-15213(計算機作業系統總結) - 第一章
技術標籤:CMU-15213(計算機作業系統總結系列)補碼c++c語言
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_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()也會導致類似的錯誤。