C語言整數型別(含取值範圍和長度)

2020-07-16 10:04:21
C語言支援 5 種帶符號的整數型別。其中大多數整數型別具有多個同義詞,見表1。

表1:帶符號的標準整數型別
型別 同義詞
signed char  
int signed, signed int
short short int, signed short, signed short int
long long int, signed long, signed long int
long long (C99) long long int, signed long long,signed long long int

對於表1列出來的 5 種帶符號整數型別,它們每個都有對應的無符號型別。與帶符號型別相比,對應的無符號型別記憶體大小相同,對齊方式(alignment)也相同。換句話說,如果編譯器將 signed int 物件對齊到偶數地址上,則 unsigned int 物件也對齊到偶數地址。表2列出了無符號型別。

表2:無符號的標準整數型別
型別 同義詞
_Bool bool(在 stdbool.h 標頭檔案中定義)
unsigned char  
unsigned int unsigned
unsigned short unsigned short int
unsigned long unsigned long int
unsigned long long unsigned long long int

C99 引入了無符號整數型別 _Bool 用來表示布林值。布林值真(true)被定義為 1,假(false)被定義為成 0。如果程式中包含 stdbool.h 標頭檔案,也可以使用識別符號 bool、true 以及 false,這是 C++ 程式設計師相當熟悉的三個關鍵字。宏 bool 是 _Bool 型別的同義字,但 true 和 false 是符號常數,它們的值分別為 1 和 0。

char 型別也是一個標準的整數型別。但是,僅有一個單詞的型別名稱 char,既可以是 signed char 的同義詞,又可以是 unsigned char 的同義詞,這由編譯器決定。因為這是由所採用的實現版本自行選擇的,所以嚴格地說,char、signed char和unsigned char 是三種不同的資料型別。

如果程式會用到的 char 值包括小於 0 或大於 127 的情況,則應該使用 signed char 或者 unsigned char,而不是 char。

可以對字元變數做算術操作。由程式自身決定是否將 char 變數的值解釋為字元碼或其他東西。例如,下面的小程式將屬於 char 型別的 ch 變數,既看成一個整數又看成一個字元,不過是在不同時刻:
char ch= 'A';                  // 資料型別為char的變數
printf("The character %c has the character code %d.n", ch, ch);
for ( ; ch <= 'Z' ; ++ch )
    printf("%2c", ch);
在 printf() 語句中,ch 先被視為一個字元以獲得顯示,然後被視為該字元的整數編碼。同樣,for 迴圈在執行 ++ch 的時候將 ch 視為整數,在執行 printf() 的時候,將 ch 視為字元。在使用 7 位 ASCII 碼或者擴充套件 ASCII 碼的系統中,上述程式程式碼將輸出以下內容:

The character A has the character code 65.
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

各種型別的長度和取值範圍

char 型別的值佔用一個位元組(換句話說,sizeof(char)總是等於1),並且 1 個位元組至少是 8 位長。基本字元集中的每個字元都可以作為一個正整數值以 char 物件表示。

對於其他標準型別,C語言只定義了其最小的儲存空間:
  • short 型別至少占用 2 個位元組;
  • long 型別至少占用 4 個位元組;
  • 而 long long 型別至少占用 8 個位元組。

此外,雖然整數型別實際所佔用的空間可能大於它們的最小空間,但是不同型別的空間大小一定遵循以下次序:

sizeof(short) ≤ sizeof(int) ≤ sizeof(long) ≤ sizeof(long long)

int 型別是最適應計算機系統架構的整數型別,它具有和 CPU 暫存器相對應的空間大小和位格式。

表3列出了標準整數型別的儲存空間大小和值範圍。

表3:標準整數型別常見儲存空間大小和取值範圍
型別 儲存空間大小 最小值 最大值
char (與 signed char 或 unsigned char 相同)  
unsigned char 1個位元組 0 255
signed char 1個位元組 -128 127
int 2個或4個位元組 -32 768 或 -2 147 483 648 32767 或 2 147 483 647
unsigned int 2個或4個位元組 0 65 535 或 4 294 967 295
short 2個位元組 -32 768 32 767
unsigned short 2個位元組 0 65 535
long 4個位元組 -2 147 483 648 2 147 483 647
unsigned long 4個位元組 0 4 294 967 295
long long (C99) 8個位元組 -9 223 372 036 854 775 808 9 223 372 036 854 775 807
Unsigned long long (C99) 8個位元組 0 18 446 744 073 709 551 615

在下面的範例中,如果系統執行平台是32位元,則int型別的iIndex和iLimit變數分別佔用4個位元組:
int iIndex,         // 定義兩個int變數
    iLimit= 1000;        // 初始化第二個
利用 sizeof 運算子,可以獲取一個資料型別或變數的空間大小。表示式 sizeof(type)輸出指定型別的大小;sizeof expression 輸出指定表示式型別的大小。輸出結果是型別為 size_t 的一組位元組。如果運算元是一個表示式,則輸出結果是該表示式的型別。
size_t 型別作為一個無符號整數型別(如 unsigned long)定義在標頭檔案 stddef.h、stdio.h,以及其他標頭檔案中。
在上述範例中,sizeof(int) 的值會和 sizeof(iIndex)一樣(都是4)。sizeof(iIndex) 的圓括號可以去掉,因為 iIndex 是一個表示式,不是一個型別。

可以在標頭檔案 limits.h 中找到所採用編譯器中整數型別的取值範圍,它們定義為宏,例如宏 INT_MIN、INT_MAX 和 UINT_MAX 等。下面的程式使用這些宏來顯示 char 和 int 型別的最小值和最大值。

例1:char和int型別的取值範圍
#include <rstdio.h>
#include <limits.h>  // 該檔案包含了CHAR_MIN、INT_MIN等宏
int main()
{
    printf("Storage sizes and value ranges of the types char and intnn");
    printf("The type char is %s.nn", CHAR_MIN<0? "signed":"unsigned");

    printf(" Type Size (in bytes)   Minimum             Maximumn"
        "--------------------------------------------------n");
    printf("char %8zu %20d %15dn", sizeof(char), CHAR_MIN, CHAR_MAX );
    printf("int %8zu %20d %15dn",  sizeof(int), INT_MIN, INT_MAX );
    return 0;
}

在標準標頭檔案中定義的整數型別

標準庫的標頭檔案針對特定用途定義了很多整數型別,例如用來顯示寬字元的 wchar_t 型別。這些型別是 typedef 名稱,它們是標準整數型別的同義詞。

型別 ptrdiff_t、size_t 和 wchar_t 定義在標頭檔案 stddef.h 中(以及其他標頭檔案中);型別 char16_t 和 char32_t 定義在標頭檔案 uchar.h 中。為了特殊需要,指定位長度的整數型別(帶符號和無符號變數)定義在標頭檔案 stdint.h 中。

此外,標頭檔案 stdint.h 也為標準庫中的所有整數型別可顯示的最大值與最小值定義了宏。例如,SIZE_MAX 等於可以在 size_t 型別變數中儲存的最大值。