c語(yǔ)言int的用法
時(shí)間:
長(zhǎng)思709由 分享
c語(yǔ)言int的用法
C 語(yǔ)言提供了很多整數(shù)類型(整型),這些整型的區(qū)別在于它們的取值范圍的大小,以及是否可以為負(fù)。int 是整型之一,一般被稱為整型。以后,在不產(chǎn)生歧義的情況下,我們把整數(shù)類型和 int 都稱為整型。下面我們來(lái)看看c語(yǔ)言int的用法。
1. 整型 int
int 代表有符號(hào)整數(shù),也就是說(shuō),用 int 聲明的變量可以是正數(shù),可以是負(fù)數(shù),也可以是零,但是只能是整數(shù)。標(biāo)準(zhǔn)規(guī)定 int 的最小取值范圍是 -32767 到 32767。int 的取值范圍因機(jī)器而異,但是一定要大于或者等于 -32767 到 32767。一般來(lái)說(shuō),int 占用一個(gè)字的內(nèi)存空間。因此,字長(zhǎng)為 16 位(Bit)的舊式 IBM 兼容機(jī)使用 16 位來(lái)儲(chǔ)存整型 int ,取值范圍是
-32768 到 32767 。目前的個(gè)人電腦一般都是 32 位字長(zhǎng)的,這些電腦中,int 一般也是 32 位的,取值范圍是 -2147483648 到 2147483647。對(duì)于使用 64 位 CPU 的電腦,使用更多位儲(chǔ)存 int 也是很自然的事情,取值范圍當(dāng)然也會(huì)更大。
2. 聲明 int 類型的變量
正如我們?cè)谝郧暗慕坛汤锟吹降哪菢?,int 用于聲明整型變量:以 int 打頭,后面跟著變量的名字,最后以分號(hào)(;)結(jié)束。例如:
int erns; /* 聲明一個(gè)變量 */
/* 注意:一定要用逗號(hào)(,),不能用分號(hào)(;)*/
int hogs, cows, goats; /* 聲明三個(gè)變量 */
以上聲明創(chuàng)建了變量,但是沒有給它們提供“值(value)”。在前面的教程中,我們已經(jīng)用了兩種方法使變量獲得“值”。一種是賦值:cows = 500; 。另一種是使用 scanf 函數(shù):scanf( "%d", &goats ); 。下面我們來(lái)學(xué)習(xí)第三種方法。
3. 初始化變量
初始化變量是指給變量賦初值:聲明變量的時(shí)候,在變量名的后面寫上等號(hào)(=),然后寫下你希望賦予變量的“值”。例如:
int hogs = 21;
int cows = 32, goats = 14;
int dogs, cats = 94;
以上聲明創(chuàng)建了變量,并且為這些變量分配了空間,同時(shí)也賦了初值。注意,第三行中只有 cats 被初始化為 94,而 dogs 沒有被初始化!如下圖:
4. int 常量
上面的例子中,21、32、14,以及 94 都是整數(shù)常量。C 語(yǔ)言中,整數(shù)常量的默認(rèn)類型是 int。如果整數(shù)常量的大小超過(guò)了 int 的取值范圍,那么編譯器將會(huì)把這個(gè)整數(shù)常量當(dāng)作 long int 類型來(lái)處理,這個(gè)我們后面還會(huì)講到。21、32、14 和 94 都在 int 的取值范圍之內(nèi),因此它們都是 int 常量。
5. 輸出 int 型數(shù)據(jù)
我們可以用 printf 函數(shù)來(lái)輸出 int 型數(shù)據(jù)。正如我們?cè)谇懊娴慕坛讨锌吹降哪菢?,占位?%d 代表輸出的是 int 型數(shù)據(jù),它告訴 printf 函數(shù)在什么地方輸出相應(yīng)的 int 型數(shù)據(jù)。%d 也被稱為格式限定符(format specifier),因?yàn)樗付?printf 函數(shù)應(yīng)該使用什么形式來(lái)輸出數(shù)據(jù)。printf 函數(shù)的第一個(gè)參數(shù)只能是字符串,這個(gè)字符串被稱為格式串(format string)。格式串中有多少個(gè) %d,我們就應(yīng)該相應(yīng)地提供多少個(gè) int 型參數(shù)給 printf 函數(shù)。int 型參數(shù)可以是 int 型變量,int 型常量,以及結(jié)果為 int 型的表達(dá)式等。例如:
int year = 2005; /* year 是 int 型變量 */
printf( "Today is %d-%d-%d ", year, 9, 20 + 9 ); /* 20 + 9 是加法表達(dá)式 */
保證格式限定符的數(shù)目和參數(shù)數(shù)目一致是我們的責(zé)任,編譯器不負(fù)責(zé)捕捉這種錯(cuò)誤!例如:
#include <stdio.h>
int main(void)
{
int ten = 10, two = 2;
printf("%d minus %d is %d ", ten ); /* 少寫了兩個(gè)參數(shù) */
getchar(); /* 等待用戶按回車 */
return 0;
}
這個(gè)程序可以通過(guò)編譯,但是運(yùn)行結(jié)果將會(huì)出乎意料,因?yàn)槲覀兩賹懥藘蓚€(gè)參數(shù)。標(biāo)準(zhǔn)規(guī)定,如果格式限定符的數(shù)目大于參數(shù)數(shù)目,則 printf 函數(shù)的行為是未定義的;如果參數(shù)數(shù)目大于格式限定符的數(shù)目,則多余的參數(shù)會(huì)被忽略。
6. 八進(jìn)制(octal)和十六進(jìn)制(hexadecimal)
C 語(yǔ)言中,整數(shù)常量默認(rèn)是十進(jìn)制(decimal)整數(shù)。通過(guò)在整數(shù)常量前面加上特定的前綴,可以把它設(shè)定為八進(jìn)制或者十六進(jìn)制整數(shù)。前綴 0x 或者 0X 把整數(shù)常量設(shè)定為十六進(jìn)制整數(shù)。注意,是數(shù)字 0 ,而不是字母 O ,別搞錯(cuò)了哦!例如:十進(jìn)制的 16 用十六進(jìn)制來(lái)表示是 0x10 或者 0X10 。在整數(shù)常量前面加上前綴 0 ,表示它是八進(jìn)制整數(shù)。注意,是數(shù)字 0 ,而不是字母 O 。例如:十進(jìn)制的 16 表示為八進(jìn)制就是 020 。
7. 以八進(jìn)制或者十六進(jìn)制形式輸出數(shù)據(jù)
使用格式限定符 %o 可以以八進(jìn)制的形式輸出整數(shù)。注意,是小寫字母 o ,不是數(shù)字 0 。使用 %x 或者 %X 可以以十六進(jìn)制的形式輸出整數(shù)。小寫 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;
}
這個(gè)程序的輸出是:
dec = 200; octal = 310; hex = c8; HEX = C8
dec = 200; octal = 0310; hex = 0xc8; HEX = 0XC8
1. 其它整數(shù)類型
int 是 C 語(yǔ)言的基本整數(shù)類型,可以滿足我們處理一般數(shù)據(jù)的需求。C 語(yǔ)言還提供了四個(gè)可以修飾 int 的關(guān)鍵字:short、long、signed,以及 unsigned。利用這四個(gè)關(guān)鍵字,C 語(yǔ)言標(biāo)準(zhǔn)定義了以下整數(shù)類型:
1) short int(可簡(jiǎn)寫為 short),和 int 一樣,也是有符號(hào)整數(shù)
2) long int(簡(jiǎn)寫:long),有符號(hào)整數(shù)
3) long long int(簡(jiǎn)寫:long long),C99 標(biāo)準(zhǔn)添加的類型,
有符號(hào)整數(shù)
4) unsigned int(簡(jiǎn)寫:unsigned),無(wú)符號(hào)整數(shù),不能表示負(fù)數(shù)
5) unsigned long int(簡(jiǎn)寫:unsigned long),無(wú)符號(hào)整數(shù),
不能表示負(fù)數(shù)
6) unsigned short int(簡(jiǎn)寫:unsigned short),無(wú)符號(hào)整數(shù),
不能表示負(fù)數(shù)
7) unsigned long long int(簡(jiǎn)寫:unsigned long long),
C99 添加的類型,無(wú)符號(hào)整數(shù)
8) 所有沒有標(biāo)明 unsigned 的整數(shù)類型默認(rèn)都是有符號(hào)整數(shù)。
在這些整數(shù)類型前面加上 signed 可以使讀者更清楚地知道
這些是有符號(hào)整數(shù),盡管有沒有 signed 都表示有符號(hào)整數(shù)。
例如:signed int 等同于 int 。
一般我們把 short 稱為短整型,把 long 稱為長(zhǎng)整型,把 long long 稱為超長(zhǎng)整型,把 int 稱為整型。unsigned 打頭的那些整數(shù)類型統(tǒng)稱為無(wú)符號(hào)整型。例如:我們稱 unsigned short 為無(wú)符號(hào)短整型。以此類推。
2. 聲明方式
這些整數(shù)類型的聲明方式與 int 類型的聲明方式一樣。例如:
long int estine;
long johns;
short int erns;
short ribs;
unsigned int s_count;
unsigned players;
unsigned long headcount;
unsigned short yesvotes;
long long ago; /* C99 特有 */
unsigned long long ego; /* C99 特有 */
如果您的編譯器不支持 C99 標(biāo)準(zhǔn),那就不能使用 long long 和 unsigned long long。
3. 取值范圍(表示范圍)
標(biāo)準(zhǔn)也規(guī)定了這些整數(shù)類型的最小取值范圍。short 的最小表示范圍和 int 一樣,都是
-32767 到 32767 。也就是 -(2^15 - 1)到(2^15 - 1)。其中,2^15表示 2 的 15 次方。類似地,2 的 20 次方記作 2^20 ,以此類推。注意:C 語(yǔ)言中 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)。
標(biāo)準(zhǔn)規(guī)定,int 的表示范圍不能小于 short 的表示范圍,long 的表示范圍不能小于 int 的表示范圍。這就是說(shuō) short 型變量占用的空間可能比 int 型變量少,而 long 型變量占用的空間可能比 int 型變量多。16 位(bit)的計(jì)算機(jī)中,int 和 short 一般都是 16 位,而 long 是 32位;32位的計(jì)算機(jī)中,short一般是 16 位,而long和int是 32位。TC2(16位的編譯器)中,int是16位的;而 Dev-C++(32 位的編譯器)中,int 是 32 位的。
使用 unsigned int 聲明的變量只能表示非負(fù)整數(shù)(0 和正整數(shù))。如果 int 是 16 位的話,那么 unsigned int 的表示范圍是 0 到 65535(2^16 - 1)。這是因?yàn)?unsigned 不需要符號(hào)位,可以把 16 個(gè)位全都用于表示整數(shù)。而 int 需要一個(gè)位作為符號(hào)位,用于表示正負(fù),只有 15 個(gè)位用于表示整數(shù)。
目前,long long 一般 64 位,long 是 32 位,short 是 16 位,而 int 或者 16 位,或者 32 位。具體某個(gè)編譯器到底使用多少位來(lái)表示這些類型,我們可以用運(yùn)算符 sizeof 來(lái)獲取。例如:
printf( "%lu ", (unsigned long)sizeof(int) * 8 ); /* 輸出 int 的位數(shù) */
printf( "%zu ", sizeof(short) * 8 ); /* 輸出 short 的位數(shù) */
sizeof 運(yùn)算符返回其操作數(shù)占用空間的大小,以字節(jié)(Byte)為單位。注意,C 定義字節(jié)的大小為 char 類型的大小。char 通常是 8 位(bit)的,當(dāng)然也可以更大。這里我們假設(shè) char 是 8 位的。點(diǎn)擊查看 char 類型詳細(xì)介紹
sizeof 的用法我們以后會(huì)講到,現(xiàn)在只要有個(gè)印象就好了。第二句中的 %zu 是 C99 特有的,如果您的編譯器不支持 C99(準(zhǔn)確地說(shuō),應(yīng)該是如果您的編譯器使用的庫(kù)函數(shù)不支持 C99),運(yùn)行結(jié)果將會(huì)出錯(cuò)。
4. 整數(shù)類型的選擇
如果您要處理的只是非負(fù)整數(shù),那么應(yīng)該優(yōu)先使用 unsigned 打頭的那些整數(shù)類型。如果您要處理的整數(shù)超出了 int 所能表示的范圍,并且您的編譯器中,long 的表示范圍比 int 大,那就使用 long。不過(guò),若非必要,盡量不要用 long,因?yàn)樗赡軙?huì)降低程序運(yùn)行效率。有一點(diǎn)要注意:如果您的編譯器中,long 和 int 都是 32 位的,并且您需要使用 32 位整數(shù),那么應(yīng)該用 long,而不要用 int。只有這樣,我們的程序才可以安全地移植到 16 位的計(jì)算機(jī),因?yàn)?16 位的計(jì)算機(jī)中,int 一般也是 16 位的。類似地,如果您需要使用 64 位整數(shù),那就用 long long。如果 int 是 32 位的話,那么使用 short 可以節(jié)省空間,不過(guò)您得確保您要處理的整數(shù)不會(huì)超出 short 的表示范圍。這種“節(jié)省”對(duì)內(nèi)存大的計(jì)算機(jī)來(lái)說(shuō),是沒什么意義的。
5. long 型常量和 long long 型常量
一般來(lái)說(shuō),整數(shù)常量是被當(dāng)作 int 類型來(lái)存儲(chǔ)的。如果我們使用的整數(shù)常量超出了 int 的表示范圍,C 語(yǔ)言規(guī)定編譯器自動(dòng)使用 unsigned int 來(lái)處理這個(gè)常量。如果 unsigned 也不足以表示這個(gè)常量的話,編譯器就會(huì)用 long。如果還表示不了的話,那就依次用 unsigned long,long long,unsigned long long。如果 unsigned long long 也表示不了,那么編譯器就沒轍了。注意:long long 和 unsigned long long 是 C99 特有的。例如:如果 int 是 16 位的話,它就表示不了常量 1000000。編譯器會(huì)使用 long 來(lái)處理這個(gè)常量,因?yàn)?unsigned int 也表示不了 1000000 。
同樣,十六進(jìn)制和八進(jìn)制整數(shù)常量通常也是被作為 int 來(lái)處理。但是,當(dāng)我們使用的常量超出了 int 的表示范圍后,編譯器會(huì)依次使用unsigned int,long,unsigned long,long long 和 unsigned long long。直到所使用的類型足以表示那個(gè)常量為止。
有時(shí),我們使用的是較小的常量,但是我們希望這個(gè)常量被當(dāng)作 long 來(lái)處理,這就需要在這個(gè)常量后面加上后綴 l(小寫字母 l)或者 L(大寫字母 L)。我們應(yīng)該避免使用 l ,因?yàn)?l 容易和數(shù)字 1 混淆。例如:整數(shù)常量 7 是被作為 int 來(lái)處理的,但整數(shù)常量 7L(或者 7l)是被作為 long 來(lái)處理的。類似地,在整數(shù)常量后面加上后綴 ll 或者 LL ,這個(gè)常量就會(huì)被當(dāng)作 long long 來(lái)處理。例如:3LL 。如果想使用無(wú)符號(hào)整數(shù)常量的話,還要配合使用后綴 u 或者 U 。例如:2u,3U,4Lu,5ul,6LU,7LLU,8Ull,9uLL 。
這些后綴也可以用于十六進(jìn)制和八進(jìn)制整數(shù)常量。例如:020L,010LL,0x30uL,0x40ull 。
1. 輸出各種整數(shù)類型的變量
輸出不同類型的整數(shù),需要使用不用的格式限定符。輸出 unsigned int 類型的整數(shù),要用 %u 。輸出 long ,要用 %ld;如果要以十六進(jìn)制或者八進(jìn)制形式輸出,那就用 %lx(或者%lX)或者 %lo。注意:雖然整數(shù)常量的后綴使用大寫或者小寫英文字母都沒關(guān)系,但是它們格式限定符必須使用小寫!如果我們要輸出 short 類型的整數(shù),可以在 %d 中間加上前綴 h,也就是%hd;同理,%ho 和 %hx(或者 %hX )分別表示以八進(jìn)制或十六進(jìn)制形式輸出。前綴 h 和 l 可以和 u 組合,表示輸出無(wú)符號(hào)整數(shù)。例如:%lu 表示輸出 unsigned long 類型的整數(shù);%hu 表示輸出unsigned short類型的整數(shù)。如果您的編譯器支持C99,可以使用 %lld 和 %llu 分別表示輸出 long long 和 unsigned long long 。下面我們來(lái)看一個(gè)輸出各種類型整數(shù)的程序:
#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++ 編譯運(yùn)行這個(gè)程序輸出結(jié)果如下:
un = 3000000000 and not -1294967296
end = 200 and 200
big = 65537 and not 1
Press ENTER to quit...
這個(gè)程序表明,錯(cuò)誤使用格式限定符會(huì)導(dǎo)致意想不到的輸出。首先,錯(cuò)誤使用 %d 來(lái)做無(wú)符號(hào)整型變量 un 的格式限定符,導(dǎo)致輸出的是負(fù)數(shù)。這是因?yàn)槲业挠?jì)算機(jī)使用相同的二進(jìn)制形式來(lái)表示 3000000000 和 -129496296 ,而計(jì)算機(jī)只認(rèn)識(shí)二進(jìn)制。所以,如果我們使用 %u 告訴 printf 輸出無(wú)符號(hào)整數(shù),輸出的就是 3000000000;如果我們誤用了 %d,那么輸出的就是一個(gè)負(fù)數(shù)。不過(guò),如果我們把代碼中的 3000000000 改成 96 的話,輸出就不會(huì)出現(xiàn)異常。因?yàn)?96 沒有超出 int 的表示范圍。
然后,對(duì)于第二個(gè) printf,無(wú)論我們使用 %hd 還是 %d,輸出的結(jié)果都是一樣的。這是因?yàn)?C 語(yǔ)言標(biāo)準(zhǔn)規(guī)定,當(dāng) short 類型值傳遞給函數(shù)時(shí),要自動(dòng)轉(zhuǎn)化成 int 類型值。之所以轉(zhuǎn)化成 int,是因?yàn)?int 被設(shè)計(jì)為計(jì)算機(jī)處理效率最高的整數(shù)類型。所以,對(duì)于 short 和 int 大小不同的計(jì)算機(jī)來(lái)說(shuō),把變量 end 轉(zhuǎn)化成 int 類型再傳遞給函數(shù),速度更快。如此說(shuō)來(lái),h 好像沒有存在意義。其實(shí)不然。我們可以用 %hd 來(lái)看看較大的整數(shù)類型被截?cái)喑?short 類型的時(shí)候會(huì)是什么樣的。
而第三個(gè) printf,由于誤用 %hd,導(dǎo)致輸出是 1。這是因?yàn)椋绻?long 是 32 位的話,65537 的二進(jìn)制形式便是 0000 0000 0000 0001 0000 0000 0000 0001,而 %hd 命令 printf 輸出 short 類型的值,從而導(dǎo)致 printf 只處理 16 位數(shù)據(jù)(假設(shè) short 是 16 位的),最終導(dǎo)致輸出 1。
在前面的教程里,我們說(shuō)過(guò),保證格式限定符的數(shù)目和參數(shù)數(shù)目一致是我們的責(zé)任。同樣,保證格式限定符的類型和參數(shù)類型一致也是我們的責(zé)任!正如上面所說(shuō)的那樣,錯(cuò)誤使用格式限定符會(huì)導(dǎo)致意想不到的輸出!標(biāo)準(zhǔn)規(guī)定,如果任意參數(shù)和與其對(duì)應(yīng)的格式限定符類型不一致,則 printf 的行為是未定義的;如果格式限定符本身就是非法的,則 printf 的行為也是未定義的。
2. 整數(shù)溢出
首先請(qǐng)看以下程序:
#include <stdio.h>
int main(void)
{
/* 32 位 int 表示范圍的上限和下限 */
int i = 2147483647, j = -2147483648;
unsigned int 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++ 編譯運(yùn)行這個(gè)程序輸出結(jié)果如下:
2147483647 -2147483648 -2147483648 2147483647
4294967295 0 1 0 4294967295
Press ENTER to quit...
本例中,i+1 是負(fù)數(shù),j-1 是正數(shù),k+1 是 0,l-1 是 4294967295 。這是因?yàn)榧訙p運(yùn)算過(guò)后,它們的值超出了它們對(duì)應(yīng)的那種整數(shù)類型的表示范圍,我們把這種現(xiàn)象稱為溢出。
unsigned int 型變量的值如果超過(guò)了上限,就會(huì)返回 0,然后從 0 開始增大。如果低于下限,那么就會(huì)到達(dá) unsigned 型的上限,然后從上限開始減小。就好像一個(gè)人繞著跑道跑步一樣,繞了一圈,又返回出發(fā)點(diǎn)。一般,int 型變量溢出的話,會(huì)變成負(fù)數(shù),或者正數(shù)。
對(duì)于 unsigned 類型的整數(shù),它們溢出時(shí)的情況一定和上面描述的一樣,這是標(biāo)準(zhǔn)規(guī)定的。但是標(biāo)準(zhǔn)并沒有規(guī)定有符號(hào)整數(shù)溢出時(shí)會(huì)出現(xiàn)什么情況。這里描述的有符號(hào)整數(shù)溢出時(shí)出現(xiàn)的情況是最常見的,但是在別的計(jì)算機(jī),使用別的編譯器,也可能出現(xiàn)不同的情況。