你真的瞭解C語言中的整型嗎?

整型數據類型

1. 整型數據類型

  在上一節當中,我們遇到了整型(integer)int,用來表示一個整數的數據類型。

  下面呢我們來討論一下C語言裏面的整數數據類型。

類型名稱 C語言中的關鍵詞 註釋
短整型 short 用於表示一個不怎麼大的整數
整型 int 生活中一般的整數都可以表示
長整型 long 較大的整數
加長整型 long long 非常大的整數

  看到這裏你可能想問,一個整數而已,爲什麼會需要定義這麼多的類型出來呢?

  要知道在發明C語言的年代,計算機資源是非常珍貴的。對內存資源,就是恨不得把一塊錢掰成兩半用的那種感覺。能用小一點的來內存來存儲,就不用大的。當然,現在大部分的強類型語言,都延續了這個傳統。即使現在內存資源以及豐富了,程序員可以在編寫代碼時,可以預想到可能的數據大小。爲什麼不讓程序員自行決定,用什麼類型呢?

  接下來,你可能想知道這些類型中,具體的大小限制是多少。很遺憾,我不能100%準確的告訴大家。因爲C語言標準並未規定這些數據類型的大小範圍,具體的實現交由了編譯器和平臺決定。那我們怎樣知道在visual studio 2019中,各種整型變量的大小呢?我們需要sizeof關鍵詞來幫我們測量。

2. 關鍵詞及sizeof關鍵詞

  和int一樣,sizeof是C語言中的一個關鍵詞。

  關鍵詞是被編譯器識別的,具有特殊意義的單詞。在C語言標準中,關鍵詞如下表所示。它們在C語言當中,都有具體的語法意義。例如int,代表一個整型數據類型,return代表函數結束並帶回返回值。

auto _Bool* break case
char _Complex* const continue
default restrict* do double
else enum extern float
for goto if _Imaginary*
inline* int long register
return short signed sizeof
static struct switch typedef
union unsigned void volatile
while

帶有*號的這些關鍵詞是C99標準新增的,在C++中並未保留。

  關鍵詞sizeof其實是【size of】去掉空格的寫法,就是某某的size的意思。如果我們想看int的大小,那麼我就可以這樣寫sizeof(int)。被執行之後,會返回一個整型。我們可以用%d來佔位,printf的用法請參照上一節。

printf("%d\n", sizeof(int));

  我們可以在自己的電腦上運行一下,檢查一下所有整型類型的size。

printf("short=%d\n", sizeof(short));
printf("int=%d\n", sizeof(int));
printf("long=%d\n", sizeof(long));
printf("long long=%d\n", sizeof(long long));

size of integer

  運行一下,我們看到了結果。

  short 爲 2, int 爲 4, long 爲 4, long long 爲 8。什麼int只能表示4?不是的,這個sizeof出來的大小是表示int所佔的字節數爲4。一個字節有8位二進制,那麼4個字節就是32位二進制。那麼32個二進制能表示多大的整數呢?

3. 各種整型類型的數值範圍


TIPS:

  如果關於整型範圍的分析暫時看不懂,請先記住sizeof的使用和各種整型變量的取值範圍即可,不影響對C語言的使用。到時候回過頭再來看取值範圍的原理分析。


  我們先暫時不要討論32個二進制,我們討論一個稍微小一點的,3個二進制。它能表示多大範圍的數值呢?

3個二進制

  請不要忘記給0位置了哦。那麼32個二進制呢?

   2 x 2 x 2 x 2 x 2 …(32個) x 2 x 2 = 2的32次方 = 4,294,967,296

   int的數值範圍爲:0 到 4,294,967,295。我們作對了嗎?

  快了,但是不全對。我們來看下面這個代碼。

負數

  對的,你肯定意識到了,負數怎麼辦?那我們需要拿出一個位來表示符號。表示這個數據是正數還是負數。在IEEE標準中,這個符號位存在於二進制的最高位。同樣的,我們來看三位二進制的情況。

補碼

  加上符號之後,現在取值範圍變爲-4到3了。紅框中的爲最高位,最高位爲1的表示負數。你可能會覺得有點奇怪,爲什麼3的二進制是011,而-3卻是101呢?如果簡單的加一個符號位,爲什麼不用111呢?那我們看看3+(-3)的運算結果。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-qeUndGBM-1589940343821)(https://oss-cpl.zhoushengjie.com/integer/3%2B(-3)].png)

  可以看到,如果用上圖中的101表示-3,那麼3+(-3)的結果是正確的。和的結果爲1000,但是我們只用3個二進制來表示數值。所以第四位被被拋棄了,也就是我們常說的溢出。但是,這個溢出卻讓我們得到了正確的結果000。而用111來表示-3,卻無法得到正確的結果。

  讓我們多算幾個,你會發現仍然是正確的。

calc

  你肯定很好奇,怎樣求一個正數對應的負數的二進制表示呢?


  1. 先寫出這個正數的二進制。
  2. 從二進制的右邊開始,遇到第一個1之前,全都填0。
  3. 遇到第一個1之後,把1填下來。
  4. 1之後的全部取反。

求補碼

  和上圖的數據對照一下看看,確實是一致的。這種負數的表示法,既通過最高位,區別了正數和負數。並且,巧妙地應用了溢出,計算結果也是正確的。因此,既然能計算負數了,那麼所有的減法,都能通過加一個負數來實現。這樣,使得計算機電路得到了簡化。這種表示負數的方法,被稱爲補碼。一個正整數的補碼是它本身,負數的補碼,通過剛剛的步驟可以求得。

  最後,你肯定發現了整數4位,二進制爲【100】,而負數4,在三位二進制表示中,也是【100】。這可咋辦呢?既然最高位是符號位了,並且,負數4的運算結果也正確。我們上面已經算過關於-4的了。那我們就只能用【100】來表示-4了。因此,3位二進制可以表達的數值範圍爲【 +(2的二次方) ~ -(2的二次方 - 1) 】,也就是-4到+3。

  終於可以回到最前面的問題了。各種整型變量的數值範圍是多少?

類型 sizeof大小 二進制位數 取值範圍算式 取值範圍
short 2 2x8 = 16位 -【2的15次方】 ~ +【2的15次方 - 1】 -32,768 ~ +32,767
int 4 4x8 = 32位 -【2的31次方】 ~ +【2的31次方 - 1】 -2,147,483,648‬ ~ + 2,147,483,647
long 4 4x8 = 32位 -【2的31次方】 ~ +【2的31次方 - 1】 -2,147,483,648‬ ~ + 2,147,483,647
long long 8 8x8 = 64位 -【2的63次方】 ~ +【2的63次方 - 1】 -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807

次方數比位數少一,是因爲最高位被用去做符號位了。

4. 無符號整型

  如果你確定你不會用到負數,那麼請使用unsigned關鍵詞。表明這個數據類型,是不帶有符號位的。既然不帶有符號位了,那麼原本留給符號位的那一個二進制位,可以用來表示數值。

類型 sizeof大小 二進制位數 取值範圍算式 取值範圍
unsigned short 2 2x8 = 16位 0 ~ +【2的16次方 - 1】 0 ~ +65,535
unsigned int 4 4x8 = 32位 0 ~ +【2的32次方 - 1】 0‬ ~ +4,294,967,295
unsigned long 4 4x8 = 32位 0 ~ +【2的32次方 - 1】 0 ~ +4,294,967,295
unsigned long long 8 8x8 = 64位 0 ~ +【2的64次方 - 1】 0 ~ +18,446,744,073,709,551,615‬

TIPS:
怎樣保證使用的整數在各個平臺上範圍統一:

  由於不同平臺的int算出來的sizeof可能不同,因此在數據範圍特別敏感的情況下。請使用頭文件stdint來定義你的變量類型。例如int32_t可以保證無論在上面平臺上,都保證sizeof大小爲32 / 8 = 4。

類型 sizeof大小 二進制位數
int8_t 1 8位
int16_t 2 2x8 = 16位
int32_t 4 4x8 = 32位
int64_t 8 8x8 = 64位
uint8_t 1 8位
uint16_t 2 2x8 = 16位
uint32_t 4 4x8 = 32位
uint64_t 8 8x8 = 64位

stdint


在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章