指針是C語言中廣泛使用的一種數(shù)據(jù)類型。 運(yùn)用指針編程是C語言最主要的風(fēng)格之一。利用指針變量可以表示各種數(shù)據(jù)結(jié)構(gòu); 能很方便地使用數(shù)組和字符串; 并能象匯編語言一樣處理內(nèi)存地址,從而編出精練而高效的程序。指針極大地豐富了C語言的功能。 學(xué)習(xí)指針是學(xué)習(xí)C語言中最重要的一環(huán), 能否正確理解和使用指針是我們是否掌握C語言的一個(gè)標(biāo)志。同時(shí), 指針也是C語言中最為困難的一部分,在學(xué)習(xí)中除了要正確理解基本概念,還必須要多編程,上機(jī)調(diào)試。只要作到這些,指針也是不難掌握的。
指針的基本概念 在計(jì)算機(jī)中,所有的數(shù)據(jù)都是存放在存儲(chǔ)器中的。 一般把存儲(chǔ)器中的一個(gè)字節(jié)稱為一個(gè)內(nèi)存單元, 不同的數(shù)據(jù)類型所占用的內(nèi)存單元數(shù)不等,如整型量占2個(gè)單元,字符量占1個(gè)單元等, 在第二章中已有詳細(xì)的介紹。為了正確地訪問這些內(nèi)存單元, 必須為每個(gè)內(nèi)存單元編上號(hào)。 根據(jù)一個(gè)內(nèi)存單元的編號(hào)即可準(zhǔn)確地找到該內(nèi)存單元。內(nèi)存單元的編號(hào)也叫做地址。 既然根據(jù)內(nèi)存單元的編號(hào)或地址就可以找到所需的內(nèi)存單元,所以通常也把這個(gè)地址稱為指針。 內(nèi)存單元的指針和內(nèi)存單元的內(nèi)容是兩個(gè)不同的概念。 可以用一個(gè)通俗的例子來說明它們之間的關(guān)系。我們到銀行去存取款時(shí), 銀行工作人員將根據(jù)我們的帳號(hào)去找我們的存款單, 找到之后在存單上寫入存款、取款的金額。在這里,帳號(hào)就是存單的指針, 存款數(shù)是存單的內(nèi)容。對(duì)于一個(gè)內(nèi)存單元來說,單元的地址即為指針, 其中存放的數(shù)據(jù)才是該單元的內(nèi)容。在C語言中, 允許用一個(gè)變量來存放指針,這種變量稱為指針變量。因此, 一個(gè)指針變量的值就是某個(gè)內(nèi)存單元的地址或稱為某內(nèi)存單元的指針。圖中,設(shè)有字符變量C,其內(nèi)容為“K”(ASCII碼為十進(jìn)制數(shù) 75),C占用了011A號(hào)單元(地址用十六進(jìn)數(shù)表示)。設(shè)有指針變量P,內(nèi)容為011A, 這種情況我們稱為P指向變量C,或說P是指向變量C的指針。 嚴(yán)格地說,一個(gè)指針是一個(gè)地址, 是一個(gè)常量。而一個(gè)指針變量卻可以被賦予不同的指針值,是變。 但在常把指針變量簡(jiǎn)稱為指針。為了避免混淆,我們中約定:“指針”是指地址, 是常量,“指針變量”是指取值為地址的變量。 定義指針的目的是為了通過指針去訪問內(nèi)存單元。
既然指針變量的值是一個(gè)地址, 那么這個(gè)地址不僅可以是變量的地址, 也可以是其它數(shù)據(jù)結(jié)構(gòu)的地址。在一個(gè)指針變量中存放一
個(gè)數(shù)組或一個(gè)函數(shù)的首地址有何意義呢? 因?yàn)閿?shù)組或函數(shù)都是連續(xù)存放的。通過訪問指針變量取得了數(shù)組或函數(shù)的首地址, 也就找到了該數(shù)組或函數(shù)。這樣一來, 凡是出現(xiàn)數(shù)組,函數(shù)的地方都可以用一個(gè)指針變量來表示, 只要該指針變量中賦予數(shù)組或函數(shù)的首地址即可。這樣做, 將會(huì)使程序的概念十分清楚,程序本身也精練,高效。在C語言中, 一種數(shù)據(jù)類型或數(shù)據(jù)結(jié)構(gòu)往往都占有一組連續(xù)的內(nèi)存單元。 用“地址”這個(gè)概念并不能很好地描述一種數(shù)據(jù)類型或數(shù)據(jù)結(jié)構(gòu), 而“指針”雖然實(shí)際上也是一個(gè)地址,但它卻是一個(gè)數(shù)據(jù)結(jié)構(gòu)的首地址, 它是“指向”一個(gè)數(shù)據(jù)結(jié)構(gòu)的,因而概念更為清楚,表示更為明確。 這也是引入“指針”概念的一個(gè)重要原因。
指針變量的類型說明
對(duì)指針變量的類型說明包括三個(gè)內(nèi)容:
(1)指針類型說明,即定義變量為一個(gè)指針變量;
(2)指針變量名;
(3)變量值(指針)所指向的變量的數(shù)據(jù)類型。
其一般形式為: 類型說明符 *變量名;
其中,*表示這是一個(gè)指針變量,變量名即為定義的指針變量名,類型說明符表示本指針變量所指向的變量的數(shù)據(jù)類型。
例如: int *p1;表示p1是一個(gè)指針變量,它的值是某個(gè)整型變量的地址。 或者說p1指向一個(gè)整型變量。至于p1究竟指向哪一個(gè)整型變量, 應(yīng)由向p1賦予的地址來決定。
再如:
staic int *p2; /*p2是指向靜態(tài)整型變量的指針變量*/
float *p3; /*p3是指向浮點(diǎn)變量的指針變量*/
char *p4; /*p4是指向字符變量的指針變量*/ 應(yīng)該注意的是,一個(gè)指針變量只能指向同類型的變量,如P3 只能指向浮點(diǎn)變量,不能時(shí)而指向一個(gè)浮點(diǎn)變量, 時(shí)而又指向一個(gè)字符變量。
指針變量的賦值
指針變量同普通變量一樣,使用之前不僅要定義說明, 而且必須賦予具體的值。未經(jīng)賦值的指針變量不能使用, 否則將造成系統(tǒng)混亂,甚至死機(jī)。指針變量的賦值只能賦予地址, 決不能賦予任何其它數(shù)據(jù),否則將引起錯(cuò)誤。在C語言中, 變量的地址是由編譯系統(tǒng)分配的,對(duì)用戶完全透明,用戶不知道變量的具體地址。 C語言中提供了地址運(yùn)算符&來表示變量的地址。其一般形式為: & 變量名; 如&a變示變量a的地址,&b表示變量b的地址。 變量本身必須預(yù)先說明。設(shè)有指向整型變量的指針變量p,如要把整型變量a 的地址賦予p可以有以下兩種方式:
(1)指針變量初始化的方法
int a;
int *p=&a;
(2)賦值語句的方法
int a;
int *p;
p=&a;
不允許把一個(gè)數(shù)賦予指針變量,故下面的賦值是錯(cuò)誤的: int *p;p=1000; 被賦值的指針變量前不能再加“*”說明符,如寫為*p=&a 也是錯(cuò)誤的
指針變量的運(yùn)算
指針變量可以進(jìn)行某些運(yùn)算,但其運(yùn)算的種類是有限的。 它只能進(jìn)行賦值運(yùn)算和部分算術(shù)運(yùn)算及關(guān)系運(yùn)算。
1.指針運(yùn)算符
(1)取地址運(yùn)算符&
取地址運(yùn)算符&是單目運(yùn)算符,其結(jié)合性為自右至左,其功能是取變量的地址。在scanf函數(shù)及前面介紹指針變量賦值中,我們已經(jīng)了解并使用了&運(yùn)算符。
(2)取內(nèi)容運(yùn)算符*
取內(nèi)容運(yùn)算符*是單目運(yùn)算符,其結(jié)合性為自右至左,用來表示指針變量所指的變量。在*運(yùn)算符之后跟的變量必須是指針變量。需要注意的是指針運(yùn)算符*和指針變量說明中的指針說明符* 不是一回事。在指針變量說明中,“*”是類型說明符,表示其后的變量是指針類型。而表達(dá)式中出現(xiàn)的“*”則是一個(gè)運(yùn)算符用以表示指針變量所指的變量。
main(){
int a=5,*p=&a;
printf (“%d”,*p);
}
……
表示指針變量p取得了整型變量a的地址。本語句表示輸出變量a的值。
2.指針變量的運(yùn)算
(1)賦值運(yùn)算
指針變量的賦值運(yùn)算有以下幾種形式:
①指針變量初始化賦值,前面已作介紹。
②把一個(gè)變量的地址賦予指向相同數(shù)據(jù)類型的指針變量。例如:
int a,*pa;
pa=&a; /*把整型變量a的地址賦予整型指針變量pa*/
③把一個(gè)指針變量的值賦予指向相同類型變量的另一個(gè)指針變量。如:
int a,*pa=&a,*pb;
pb=pa; /*把a(bǔ)的地址賦予指針變量pb*/
由于pa,pb均為指向整型變量的指針變量,因此可以相互賦值。
④把數(shù)組的首地址賦予指向數(shù)組的指針變量。
例如:
int a[5],*pa;
pa=a; (數(shù)組名表示數(shù)組的首地址,故可賦予指向數(shù)組的指針變量pa)
也可寫為:
pa=&a[0]; /*數(shù)組第一個(gè)元素的地址也是整個(gè)數(shù)組的首地址,
也可賦予pa*/
當(dāng)然也可采取初始化賦值的方法:
int a[5],*pa=a;
⑤把字符串的首地址賦予指向字符類型的指針變量。例如: char *pc;pc=”c language”;或用初始化賦值的方法寫為: char *pc=”C Language”; 這里應(yīng)說明的是并不是把整個(gè)字符串裝入指針變量, 而是把存放該字符串的字符數(shù)組的首地址裝入指針變量。 在后面還將詳細(xì)介紹。
⑥把函數(shù)的入口地址賦予指向函數(shù)的指針變量。例如: int (*pf)();pf=f; /*f為函數(shù)名*/