C語言int型(2位元組)數據的值的範圍為什麼是-2^15~(2^15-1)?

為什麼要-1?


計算機整數使用補碼錶示。

1. 為什麼用補碼?

因為補碼相加的話,加法器的邏輯電路不需要做偏移修正。你可以試一下1+(-1)的原碼和補碼就明白了。

2. 補碼的話,對於int16而言,最高位是符號位,後面是15位數據位。因為整數非負的時候補碼和原碼一致,負數時為按位取反+1。所以最小的非負是16個0,最大的非負是0後面15個1,最大的負數是16個1,最小的負數是1後面15個0。

綜合以上,所以int16的表示範圍是-2^{15} 到 2^{15}-1


不問是不是,就問為什麼。。。

C語言標準根本不定各種整形的具體尺寸,何來固定的數值範圍?我要是搞個鬼畜的系統,一位元組10位,然後定int為8位元組,怎麼辦?

===============================

實際上,由於int通常使用補碼錶示負數,這樣一來,符號位為0的零值是零,而符號位為1的負數範圍不需要表示0,就額外多了一個可用的數。比如以四位為例:

0000:0
0001:1
0010:2
0011:3
0100:4
0101:5
0110:6
0111:7
1000:-8
1001:-7
1010:-6
1011:-5
1100:-4
1101:-3
1110:-2
1111:-1


2byte int能最大數是8FFF,也就是2^{15}-1


根本沒有的事情。

不要連事實都沒搞清楚就提問


樓上已經說明了因為 0 佔一個位子。具體需要了解二進位的存儲方式:

負數最高 bit 是 1 代表負數,0 代表正數,其他 bit 在內存中的存儲是「~(負數的相反數 - 1)」。

以下以 2 bytes 有符號整形為例說明,來看 -2 如何在內存中存儲。

=&> ~(2 - 1)

=&> ~(000 0000 0000 0010 - 1)

=&> ~000 0000 0000 0001

=&> 111 1111 1111 1110 (不含符號位的其餘部分)

=&> 1111 1111 1111 1110 (包含符號位的完整二進位)

同理 -1 的二進位為 1111 1111 1111 1111。

從二進位反推十進位負數,則 1000 0000 0000 0000 表示:

1000 0000 0000 0000 (包含符號位的完整二進位)

=&> 000 0000 0000 0000 (不含符號位的其餘部分)

=&> ~111 1111 1111 1111

=&> ~(1000 0000 0000 0000 - 1)

=&> ~(2^{15} - 1) 或 ~(32768 - 1)

其表示的負數為 -32768 (-2^{15} )。

正數由於最高符號位必須為 0,則其最大值為:

=&> 0111 1111 1111 1111

=&> 1000 0000 0000 0000 - 1

=&> 2^{15} - 1 或 32768 - 1

即 2 bytes 所能表示的負數最小到 -32768,加上 0,以及正數 1~32767 (0111 1111 1111 1111)。


10000000 00000000(第一位表示符號)是2位元組中最小數,是負數,是10000000 00000000的補碼,十進位中是-2∧15;011111111 11111111是最大數,是正數。轉換成十進位是2∧15-1。

||也可以這樣理解0~32767共有32768個數(二進位碼以0開頭),-1~-32768共有32768個數(二進位碼以1開頭),這樣想強迫症估計能緩解下。


補碼錶示規則要求這樣


這種問題,還是要多看書啊。


因為0也是一個值


推薦閱讀:

C++域作用符在函數聲明和定義中的意義?
在 64 位平台開發時是否應盡量避免使用指針?
C++中為什麼派生類中只有基本類型時,delete一個指向派生類的基類指針時卻沒有內存泄漏?
c++在執行運行時多態時,為什麼需要借用rtti來判斷對象真實類型?
一個關於C++模板的問題?

TAG:編程語言 | C編程語言 | CC | 計算機原理 | C語言入門 |