C語言基本數據類型:整型(int)用法詳解

C語言基本數據類型:整型(int)用法詳解 
 
1. 整型int 
    C 語言提供了很多整數類型(整型),這些整型的區別在於它們的取值範圍的大小,以及是否可以爲負。int是整型之一,一般被稱爲整型。以後,在不產生歧義的情況下,我們把整數類型和int都稱爲整型。  
int代表有符號整數,也就是說,用int聲明的變量可以是正數,可以是負數,也可以是零,但是隻能是整數。標準規定int的最小取值範圍是 -32767 到 32767。int的取值範圍因機器而異,但是一定要大於或者等於 -32767 到 32767。一般來說,int佔用一個字的內存空間。因此,字長爲 16 位(Bit)的舊式 IBM 兼容機使用 16 位來儲存整型int,取值範圍是 -32768 到 32767 。目前的個人電腦一般都是 32 位字長的,這些電腦中,int一般也是 32 位的,取值範圍是 -2147483648 到 2147483647。對於使用 64 位 CPU 的電腦,使用更多位儲存int也是很自然的事情,取值範圍當然也會更大。  
2. 聲明int類型的變量 
正如我們在以前的教程裏看到的那樣,int用於聲明整型變量:以int打頭,後面跟着變量的名字,最後以分號(;)結束。例如: interns; /* 聲明一個變量 */ 
/* 注意:一定要用逗號(,),不能用分號(;)*/ int hogs, cows, goats; /* 聲明三個變量 */ 
以上聲明創建了變量,但是沒有給它們提供“值(value)”。在前面的教程中,我們已經用了兩種方法使變量獲得“值”。一種是賦值:cows = 500; 。另一種是使用scanf函數:scanf( "%d", &goats ); 。下面我們來學習第三種方法。  
3. 初始化變量 
初始化變量是指給變量賦初值:聲明變量的時候,在變量名的後面寫上等號(=),然後寫下你希望賦予變量的“值”。例如: int hogs = 21; 
int cows = 32, goats = 14; 
int dogs, cats = 94; 
以上聲明創建了變量,並且爲這些變量分配了空間,同時也賦了初值。注意,第三行中只有 cats 被初始化爲 94,而 dogs 沒有被初始化!如下圖:  
 
4. int常量 
上面的例子中,21、32、14,以及 94 都是整數常量。C 語言中,整數常量的默認類型是int。如果整數常量的大小超過了int的取值範圍,那麼編譯器將會把這個整數常量當作 long int類型來處理,這個我們後面還會講到。21、32、14 和 94 都在int的取值範圍之內,因此它們都是int常量。  
5. 輸出int型數據  
我們可以用printf函數來輸出int型數據。正如我們在前面的教程中看到的那樣,佔位符 %d代表輸出的是int型數據,它告訴printf函數在什麼地方輸出相應的int型數據。%d 也被稱爲格式限定符(format specifier),因爲它指定了printf函數應該使用什麼形式來輸出數據。printf函數的第一個參數只能是字符串,這個字符串被稱爲格式串(format string)。格式串中有多少個 %d,我們就應該相應地提供多少個int型參數給printf函數。int型參數可以是int型變量,int型常量,以及結果爲int型的表達式等。例如: int year = 2005; /* year 是int型變量 */ 
printf( "Today is %d-%d-%d ", year, 9, 20 + 9 ); /* 20 + 9 是加法表達式 */ 
保證格式限定符的數目和參數數目一致是我們的責任,編譯器不負責捕捉這種錯誤!例如: #include <stdio.h> int main(void) { 
int ten = 10, two = 2; 
printf("%d minus %d is %d ", ten ); /* 少寫了兩個參數 */ getchar(); /* 等待用戶按回車 */ return 0; } 
這個程序可以通過編譯,但是運行結果將會出乎意料,因爲我們少寫了兩個參數。標準規定,如果格式限定符的數目大於參數數目,則printf函數的行爲是未定義的;如果參數數目大於格式限定符的數目,則多餘的參數會被忽略。  
6. 八進制(octal)和十六進制(hexadecimal) 
C 語言中,整數常量默認是十進制(decimal)整數。通過在整數常量前面加上特定的前綴,可以把它設定爲八進制或者十六進制整數。前綴 0x 或者 0X 把整數常量設定爲十六進制整數。注意,是數字 0 ,而不是字母 O ,別搞錯了哦!例如:十進制的 16 用十六進制來表示是 0x10 或者 0X10 。在整數常量前面加上前綴 0 ,表示它是八進制整數。注意,是數字 0 ,而不是字母 O 。例如:十進制的 16 表示爲八進制就是 020 。  
7. 以八進制或者十六進制形式輸出數據 
使用格式限定符 %o 可以以八進制的形式輸出整數。注意,是小寫字母 o ,不是數字 0 。使用 %x 或者 %X 可以以十六進制的形式輸出整數。小寫 x 表示輸出使用小寫字母,大寫 X 表示輸出使用大寫字母。使用 %#o,%#x 或者 %#X,得到的輸出將包括前綴 0,0x 或者 0X。例如: #include <stdio.h> int main(void) { 
int x = 200; 
printf("dec = %d; octal = %o; hex = %x; HEX = %X ", x, x, x, x); printf("dec = %d; octal = %#o; hex = %#x; HEX = %#X ", x, x, x, x); getchar(); return 0; } 
這個程序的輸出是: 
dec = 200; octal = 310; hex = c8; HEX = C8 
dec = 200; octal = 0310; hex = 0xc8; HEX = 0XC8 

1. 其它整數類型 
int是 C 語言的基本整數類型,可以滿足我們處理一般數據的需求。C 語言還提供了四個可以修飾int的關鍵字:short、long、signed,以及 unsigned。利用這四個關鍵字,C 語言標準定義了以下整數類型: 1) short int(可簡寫爲 short),和int一樣,也是有符號整數 2) long int(簡寫:long),有符號整數 3) long longint(簡寫:long long),C99 標準添加的類型, 有符號整數 
4) unsigned int(簡寫:unsigned),無符號整數,不能表示負數 5) unsigned long int(簡寫:unsigned long),無符號整數, 不能表示負數 
6) unsigned short int(簡寫:unsigned short),無符號整數, 不能表示負數 
7) unsigned long longint(簡寫:unsigned long long), 
         C99 添加的類型,無符號整數 
8) 所有沒有標明 unsigned 的整數類型默認都是有符號整數。 在這些整數類型前面加上 signed 可以使讀者更清楚地知道 這些是有符號整數,儘管有沒有 signed 都表示有符號整數。 例如:signed int等同於int。 
一般我們把 short 稱爲短整型,把 long 稱爲長整型,把 long long稱爲超長整型,把int稱爲整型。unsigned 打頭的那些整數類型統稱爲無符號整型。例如:我們稱 unsigned short 爲無符號短整型。以此類推。  
2. 聲明方式 
這些整數類型的聲明方式與int類型的聲明方式一樣。例如: longintestine; long johns; shortinterns; short ribs; 
unsignedints_count; unsigned players; 
unsigned long headcount; unsigned short yesvotes; 
long longago; /* C99 特有 */ 
unsigned long long ego; /* C99 特有 */ 
如果您的編譯器不支持 C99 標準,那就不能使用 long long和 unsigned long long。  
3. 取值範圍(表示範圍) 
標準也規定了這些整數類型的最小取值範圍。short 的最小表示範圍和int一樣,都是 -32767 到 32767 。也就是 -(2^15 - 1)到(2^15 - 1)。其中,2^15表示 2 的 15 次方。類似地,2 的 20 次方記作 2^20 ,以此類推。注意:C 語言中 2^15 並不表示 2 的 15 次方,爲了書寫方便,我們姑且這麼表示。long 的最小取值範圍是 -2147483647 到 2147483647 。也就是 -(2^31 - 1) 到 (2^31 - 1) 。unsigned short的最小表示範圍和unsigned int一樣,都是 0 到 65535(2^16 - 1)。unsigned long 的最小取值範圍是 0 到 4294967295(2^32 - 1)。long long的最小取值範圍是 -9223372036854775807(-(2^63 - 1))到 9223372036854775807(2^63 - 1);unsigned long long是 0 到 18446744073709551615(2^64 - 1)。 
標準規定,int的表示範圍不能小於 short 的表示範圍,long 的表示範圍不能小於int的表示範圍。這就是說 short 型變量佔用的空間可能比int型變量少,而 long 型變量佔用的空間可能比int型變量多。16 位(bit)的計算機中,int和 short 一般都是 16 位,而 long 是 32位;32位的計算機中,short一般是 16 位,而long和int是 32位。TC2(16位的編譯器)中,int是16位的;而Dev-C++(32 位的編譯器)中,int是 32 位的。 
使用 unsigned int聲明的變量只能表示非負整數(0 和正整數)。如果int是 16 位的話,那麼 unsigned int的表示範圍是 0 到 65535(2^16 - 1)。這是因爲 unsigned 不需要符號位,可以把 16 個位全都用於表示整數。而int需要一個位作爲符號位,用於表示正負,只有 15 個位用於表示整數。 
目前,long long一般 64 位,long 是 32 位,short 是 16 位,而int或者 16 位,或者 32 位。具體某個編譯器到底使用多少位來表示這些類型,我們可以用運算符sizeof來獲取。例如: 
printf( "%lu ", (unsigned long)sizeof(int) * 8 ); /* 輸出int的位數 */ printf( "%zu ", sizeof(short) * 8 ); /* 輸出 short 的位數 */ 
sizeof運算符返回其操作數佔用空間的大小,以字節(Byte)爲單位。注意,C 定義字節的大小爲 char 類型的大小。char 通常是 8 位(bit)的,當然也可以更大。這裏我們假設 char 是 8 位的。點擊查看 char 類型詳細介紹 
sizeof的用法我們以後會講到,現在只要有個印象就好了。第二句中的 %zu是 C99 特有的,如果您的編譯器不支持 C99(準確地說,應該是如果您的編譯器使用的庫函數不支持 C99),運行結果將會出錯。  
4. 整數類型的選擇 
如果您要處理的只是非負整數,那麼應該優先使用 unsigned 打頭的那些整數類型。如果您要處理的整數超出了int所能表示的範圍,並且您的編譯器中,long 的表示範圍比int大,那就使用 long。不過,若非必要,儘量不要用 long,因爲它可能會降低程序運行效率。有一點要注意:如果您的編譯器中,long 和int都是 32 位的,並且您需要使用 32 位整數,那麼應該用 long,而不要用int。只有這樣,我們的程序纔可以安全地移植到 16 位的計算機,因爲 16 位的計算機中,int一般也是 16 位的。類似地,如果您需要使用 64 位整數,那就用 long long。如果int是 32 位的話,那麼使用 short 可以節省空間,不過您得確保您要處理的整數不會超出 short 的表示範圍。這種“節省”對內存大的計算機來說,是沒什麼意義的。  
5. long 型常量和 long long型常量 
一般來說,整數常量是被當作int類型來存儲的。如果我們使用的整數常量超出了int的表示範圍,C 語言規定編譯器自動使用 unsigned int來處理這個常量。如果 unsigned 也不足以表示這個常量的話,編譯器就會用 long。如果還表示不了的話,那就依次用 unsigned long,long long,unsigned long long。如果 unsigned long long也表示不了,那麼編譯器就沒轍了。注意:long long和 unsigned long long是 C99 特有的。例如:如果int是 16 位的話,它就表示不了常量 1000000。編譯器會使用 long 來處理這個常量,因爲 unsigned int也表示不了 1000000 。 同樣,十六進制和八進制整數常量通常也是被作爲int來處理。但是,當我們使用的常量超出了int的表示範圍後,編譯器會依次使用unsigned int,long,unsigned long,long long和 unsigned long long。直到所使用的類型足以表示那個常量爲止。 
有時,我們使用的是較小的常量,但是我們希望這個常量被當作 long 來處理,這就需要在這個常量後面加上後綴 l(小寫字母 l)或者 L(大寫字母 L)。我們應該避免使用 l ,因爲 l 容易和數字 1 混淆。例如:整數常量 7 是被作爲int來處理的,但整數常量 7L(或者 7l)是被作爲 long 來處理的。類似地,在整數常量後面加上後綴ll或者 LL ,這個常量就會被當作 long long來處理。例如:3LL 。如果想使用無符號整數常量的話,還要配合使用後綴 u 或者 U 。例如:2u,3U,4Lu,5ul,6LU,7LLU,8Ull,9uLL 。 
這些後綴也可以用於十六進制和八進制整數常量。例如:020L,010LL,0x30uL,0x40ull 。  
1. 輸出各種整數類型的變量 
輸出不同類型的整數,需要使用不用的格式限定符。輸出 unsigned int類型的整數,要用 %u 。輸出 long ,要用 %ld;如果要以十六進制或者八進制形式輸出,那就用 %lx(或者%lX)或者 %lo。注意:雖然整數常量的後綴使用大寫或者小寫英文字母都沒關係,但是它們格式限定符必須使用小寫!如果我們要輸出 short 類型的整數,可以在 %d 中間加上前綴 h,也就是%hd;同理,%ho 和 %hx(或者 %hX)分別表示以八進制或十六進制形式輸出。前綴 h 和 l 可以和 u 組合,表示輸出無符號整數。例如:%lu表示輸出 unsigned long 類型的整數;%hu表示輸出unsigned short類型的整數。如果您的編譯器支持C99,可以使用 %lld和 %llu分別表示輸出 long long和 unsigned long long。下面我們來看一個輸出各種類型整數的程序: 
        #include <stdio.h> int main(void)         { 
unsigned int un = 3000000000; /* 我使用的編譯器int是 32 位的 */ short end = 200; /* 而 short 是 16 位的 */ long big = 65537; 
printf("un = %u and not %d ", un, un); printf("end = %hd and %d ", end, end); printf("big = %ld and not %hd ", big, big); printf("Press ENTER to quit..."); getchar(); return 0;         } 
使用Dev-C++ 編譯運行這個程序輸出結果如下: un = 3000000000 and not -1294967296 end = 200 and 200 
big = 65537 and not 1 
        Press ENTER to quit... 
這個程序表明,錯誤使用格式限定符會導致意想不到的輸出。首先,錯誤使用 %d 來做無符號整型變量 un 的格式限定符,導致輸出的是負數。這是因爲我的計算機使用相同的二進制形式來表示 3000000000 和 -129496296 ,而計算機只認識二進制。所以,如果我們使用 %u 告訴printf輸出無符號整數,輸出的就是 3000000000;如果我們誤用了 %d,那麼輸出的就是一個負數。不過,如果我們把代碼中的 3000000000 改成 96 的話,輸出就不會出現異常。因爲 96 沒有超出int的表示範圍。 
然後,對於第二個printf,無論我們使用 %hd還是 %d,輸出的結果都是一樣的。這是因爲 C 語言標準規定,當 short 類型值傳遞給函數時,要自動轉化成int類型值。之所以轉化成int,是因爲int被設計爲計算機處理效率最高的整數類型。所以,對於 short 和int大小不同的計算機來說,把變量 end 轉化成int類型再傳遞給函數,速度更快。如此說來,h 好像沒有存在意義。其實不然。我們可以用 %hd來看看較大的整數類型被截斷成 short 類型的時候會是什麼樣的。 
而第三個printf,由於誤用 %hd,導致輸出是 1。這是因爲,如果 long 是 32 位的話,65537 的二進制形式便是 0000 0000 0000 0001 0000 0000 0000 0001,而 %hd命令printf輸出 short 類型的值,從而導致printf只處理 16 位數據(假設 short 是 16 位的),最終導致輸出 1。 在前面的教程裏,我們說過,保證格式限定符的數目和參數數目一致是我們的責任。同樣,保證格式限定符的類型和參數類型一致也是我們的責任!正如上面所說的那樣,錯誤使用格式限定符會導致意想不到的輸出!標準規定,如果任意參數和與其對應的格式限定符類型不一致,則printf的行爲是未定義的;如果格式限定符本身就是非法的,則printf的行爲也是未定義的。  
2. 整數溢出 
首先請看以下程序: #include <stdio.h> int main(void) { 
/* 32 位int表示範圍的上限和下限 */ int i = 2147483647, j = -2147483648; unsignedint k = 4294967295, l = 0; printf("%d %d %d %d ", i, i+1, j, j-1); printf("%u %u %u %u %u ", k, k+1, k+2, l, l-1); printf("Press ENTER to quit..."); getchar(); return 0; } 
使用Dev-C++ 編譯運行這個程序輸出結果如下:  2147483647 -2147483648 -2147483648 2147483647 4294967295 0 1 0 4294967295 Press ENTER to quit... 
本例中,i+1 是負數,j-1 是正數,k+1 是 0,l-1 是 4294967295 。這是因爲加減運算過後,它們的值超出了它們對應的那種整數類型的表示範圍,我們把這種現象稱爲溢出。 unsigned int型變量的值如果超過了上限,就會返回 0,然後從 0 開始增大。如果低於下限,那麼就會到達 unsigned 型的上限,然後從上限開始減小。就好像一個人繞着跑道跑步一樣,繞了一圈,又返回出發點。一般,int型變量溢出的話,會變成負數,或者正數。 
對於 unsigned 類型的整數,它們溢出時的情況一定和上面描述的一樣,這是標準規定的。但是標準並沒有規定有符號整數溢出時會出現什麼情況。這裏描述的有符號整數溢出時出現的情況是最常見的,但是在別的計算機,使用別的編譯器,也可能出現不同的情況。




 



發佈了48 篇原創文章 · 獲贊 9 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章