輕鬆學會C語言:[9]指標?

陣列名和陣列指標變數作函式引數  在第五章中曾經介紹過用陣列名作函式的實參和形參的問題。在學習指標變數之後就更容易理解這個問題了。
陣列名就是陣列的首地址,實參向形參傳送陣列名實際上就是傳送陣列的地址, 形參得到該地址後也指向同一陣列。
這就好象同一件物品有兩個彼此不同的名稱一樣。同樣,指標變數的值也是地址, 陣列指標變數的值即為陣列的首地址,當然也可作為函式的引數使用。float aver(float *pa);main(){float sco[5],av,*sp;int
i;sp=sco;printf("\ninput 5 scores:\n");for(i=0;i<5;i++)
scanf("%f",&sco[i]);av=aver(sp);printf("average score is
%5.2f",av);}float aver(float *pa){int i;float
av,s=0;for(i=0;i<5;i++) s=s+*pa++;av=s/5;return
av;}指向多維陣列的指標變數本小節以二維陣列為例介紹多維陣列的指標變數。一、多維陣列地址的表示方法設有整型二維陣列a[3][4]如下:0 1 2 34 5 6 78 9 10 11  設陣列a的首地址為1000,各下標變數的首地址及其值如圖所示。在第四章中介紹過,
C語言允許把一個二維陣列分解為多個一維陣列來處理。因此陣列a可分解為三個一維陣列,即a[0],a[1],a[2]。每一個一維陣列又含有四個元素。例如a[0]陣列,含有a[0][0],a[0][1],a[0][2],a[0][3]四個元素。
陣列及陣列元素的地址表示如下:a是二維陣列名,也是二維陣列0行的首地址,等於1000。a[0]是第一個一維陣列的陣列名和首地址,因此也為1000。*(a+0)或*a是與a[0]等效的,
它表示一維陣列a[0]0 號元素的首地址。
也為1000。&a[0][0]是二維陣列a的0行0列元素首地址,同樣是1000。因此,a,a[0],*(a+0),*a,&a[0][0]是相等的。同理,a+1是二維陣列1行的首地址,等於1008。a[1]是第二個一維陣列的陣列名和首地址,因此也為1008。
&a[1][0]是二維陣列a的1行0列元素地址,也是1008。因此a+1,a[1],*(a+1),&a[1][0]是等同的。
由此可得出:a+i,a[i],*(a+i),&a[i][0]是等同的。
此外,&a[i]和a[i]也是等同的。因為在二維陣列中不能把&a[i]理解為元素a[i]的地址,不存在元素a[i]。  C語言規定,它是一種地址計算方法,表示陣列a第i行首地址。由此,我們得出:a[i],&a[i],*(a+i)和a+i也都是等同的。另外,a[0]也可以看成是a[0]+0是一維陣列a[0]的0號元素的首地址,
而a[0]+1則是a[0]的1號元素首地址,由此可得出a[i]+j則是一維陣列a[i]的j號元素首地址,它等於&a[i][j]。由a[i]=*(a+i)得a[i]+j=*(a+i)+j,由於*(a+i)+j是二維陣列a的i行j列元素的首地址。該元素的值等於*(*(a+i)+j)。[Explain]#define PF "%d,%d,%d,%d,%d,\n"main(){static int
a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};printf(PF,a,*a,a[0],&a[0],&a[0][0]);printf(PF,a+1,*(a+1),a[1],&a[1],&a[1][0]);printf(PF,a+2,*(a+2),a[2],&a[2],&a[2][0]);printf("%d,%d\n",a[1]+1,*(a+1)+1);printf("%d,%d\n",*(a[1]+1),*(*(a+1)+1));}二、多維陣列的指標變數  把二維陣列a
分解為一維陣列a[0],a[1],a[2]之後,設p為指向二維陣列的指標變數。可定義為: int (*p)[4] 它表示p是一個指標變數,它指向二維陣列a
或指向第一個一維陣列a[0],其值等於a,a[0],或&a[0][0]等。而p+i則指向一維陣列a[i]。從前面的分析可得出*(p+i)+j是二維陣列i行j
列的元素的地址,而*(*(p+i)+j)則是i行j列元素的值。  二維陣列指標變數說明的一般形式為: 型別說明符 (*指標變數名)[長度]
其中“型別說明符”為所指陣列的資料型別。“*”表示其後的變數是指標型別。 “長度”表示二維陣列分解為多個一維陣列時,
一維陣列的長度,也就是二維陣列的列數。應注意“(*指標變數名)”兩邊的括號不可少,如缺少括號則表示是指標陣列(本章後面介紹),意義就完全不同了。[Explain]main(){static int
a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};int(*p)[4];int
i,j;p=a;for(i=0;i<3;i++)for(j=0;j<4;j++) printf("%2d
",*(*(p+i)+j));}'Expain字串指標變數的說明和使用字串指標變數的定義說明與指向字元變數的指標變數說明是相同的。只能按對指標變數的賦值不同來區別。
對指向字元變數的指標變數應賦予該字元變數的地址。如: char c,*p=&c;表示p是一個指向字元變數c的指標變數。而: char *s="C
Language";則表示s是一個指向字串的指標變數。把字串的首地址賦予s。請看下面一例。main(){char *ps;ps="C
Language";printf("%s",ps);}執行結果為:C Language上例中,首先定義ps是一個字元指標變數,
然後把字串的首地址賦予ps(應寫出整個字串,以便編譯系統把該串裝入連續的一塊記憶體單元),並把首地址送入ps。程式中的: char *ps;ps="C
Language";等效於: char *ps="C Language";輸出字串中n個字元後的所有字元。main(){char *ps="this is a book";int
n=10;ps=ps+n;printf("%s\n",ps);}執行結果為:book
在程式中對ps初始化時,即把字串首地址賦予ps,當ps= ps+10之後,ps指向字元“b”,因此輸出為"book"。main(){char st[20],*ps;int i;printf("input a
string:\n");ps=st;scanf("%s",ps);for(i=0;ps[i]!='\0';i++)if(ps[i]=='k'){printf("there
is a 'k' in the string\n");break;}if(ps[i]=='\0') printf("There is
no 'k' in the string\n");}  本例是在輸入的字串中查詢有無‘k’字元。
下面這個例子是將指標變數指向一個格式字串,用在printf函式中,用於輸出二維陣列的各種地址表示的值。但在printf語句中用指標變數PF代替了格式串。
這也是程式中常用的方法。main(){static int
a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};char
*PF;PF="%d,%d,%d,%d,%d\n";printf(PF,a,*a,a[0],&a[0],&a[0][0]);printf(PF,a+1,*(a+1),a[1],&a[1],&a[1][0]);printf(PF,a+2,*(a+2),a[2],&a[2],&a[2][0]);printf("%d,%d\n",a[1]+1,*(a+1)+1);printf("%d,%d\n",*(a[1]+1),*(*(a+1)+1));}  在下例是講解,把字串指標作為函式引數的使用。要求把一個字串的內容複製到另一個字串中,並且不能使用strcpy函式。函式cprstr的形參為兩個字元指標變數。pss指向源字串,pds指向目標字串。表示式:(*pds=*pss)!=`\0'cpystr(char *pss,char
*pds){while((*pds=*pss)!='\0'){pds++;pss++;
}}main(){char
*pa="CHINA",b[10],*pb;pb=b;cpystr(pa,pb);printf("string a=%s\nstring
b=%s\n",pa,pb);}  在上例中,程式完成了兩項工作:一是把pss指向的源字元複製到pds所指向的目標字元中,二是判斷所複製的字元是否為`\0',若是則表明源字串結束,不再迴圈。否則,pds和pss都加1,指向下一字元。在主函式中,以指標變數pa,pb為實參,分別取得確定值後呼叫cprstr函式。由於採用的指標變數pa和pss,pb和pds均指向同一字串,因此在主函式和cprstr函式中均可使用這些字串。也可以把cprstr函式簡化為以下形式:cprstr(char *pss,char*pds){while
((*pds++=*pss++)!=`\0');}  即把指標的移動和賦值合併在一個語句中。
進一步分析還可發現`\0'的ASCⅡ碼為0,對於while語句只看表示式的值為非0就迴圈,為0則結束迴圈,因此也可省去“!=`\0'”這一判斷部分,而寫為以下形式:cprstr
(char *pss,char *pds){while (*pdss++=*pss++);}表示式的意義可解釋為,源字元向目標字元賦值,
移動指標,若所賦值為非0則迴圈,否則結束迴圈。這樣使程式更加簡潔。簡化後的程式如下所示。cpystr(char
*pss,char *pds){while(*pds++=*pss++);}main(){char
*pa="CHINA",b[10],*pb;pb=b;cpystr(pa,pb);printf("string a=%s\nstring
b=%s\n",pa,pb);}使用字串指標變數與字元陣列的區別用字元陣列和字元指標變數都可實現字串的儲存和運算。
但是兩者是有區別的。在使用時應注意以下幾個問題:1.
字串指標變數本身是一個變數,用於存放字串的首地址。而字串本身是存放在以該首地址為首的一塊連續的記憶體空間中並以‘\0’作為串的結束。字元陣列是由於若干個陣列元素組成的,它可用來存放整個字串。2.
對字元陣列作初始化賦值,必須採用外部型別或靜態型別,如: static char st[]={“C Language”};而對字串指標變數則無此限制,如:
char *ps="C Language";3. 對字串指標方式 char *ps="C Language";可以寫為: char
*ps; ps="C Language";而對陣列方式:static char st[]={"C
Language"};不能寫為:char st[20];st={"C
Language"};而只能對字元陣列的各元素逐個賦值。  從以上幾點可以看出字串指標變數與字元陣列在使用時的區別,同時也可看出使用指標變數更加方便。前面說過,當一個指標變數在未取得確定地址前使用是危險的,容易引起錯誤。但是對指標變數直接賦值是可以的。因為C系統對指標變數賦值時要給以確定的地址。因此,char *ps="C Langage";或者 char *ps;ps="C Language";都是合法的。函式指標變數  在C語言中規定,一個函式總是佔用一段連續的記憶體區,
而函式名就是該函式所佔記憶體區的首地址。 我們可以把函式的這個首地址(或稱入口地址)賦予一個指標變數,
使該指標變數指向該函式。然後通過指標變數就可以找到並呼叫這個函式。
我們把這種指向函式的指標變數稱為“函式指標變數”。函式指標變數定義的一般形式為:型別說明符 (*指標變數名)();其中“型別說明符”表示被指函式的返回值的型別。“(* 指標變數名)”表示“*”後面的變數是定義的指標變數。
最後的空括號表示指標變數所指的是一個函式。例如: int
(*pf)();表示pf是一個指向函式入口的指標變數,該函式的返回值(函式值)是整型。下面通過例子來說明用指標形式實現對函式呼叫的方法。int max(int a,int b){if(a>b)return a;else return
b;}main(){int max(int a,int b);int(*pmax)();int
x,y,z;pmax=max;printf("input two
numbers:\n");scanf("%d%d",&x,&y);z=(*pmax)(x,y);printf("maxmum=%d",z);}  從上述程式可以看出用,函式指標變數形式呼叫函式的步驟如下:1.
先定義函式指標變數,如後一程式中第9行 int (*pmax)();定義pmax為函式指標變數。2.
把被調函式的入口地址(函式名)賦予該函式指標變數,如程式中第11行 pmax=max;3. 用函式指標變數形式呼叫函式,如程式第14行
z=(*pmax)(x,y); 呼叫函式的一般形式為: (*指標變數名) (實參表)使用函式指標變數還應注意以下兩點:a.
函式指標變數不能進行算術運算,這是與陣列指標變數不同的。陣列指標變數加減一個整數可使指標移動指向後面或前面的陣列元素,而函式指標的移動是毫無意義的。b.
函式呼叫中"(*指標變數名)"的兩邊的括號不可少,其中的*不應該理解為求值運算,在此處它只是一種表示符號。指標型函式前面我們介紹過,所謂函式型別是指函式返回值的型別。
在C語言中允許一個函式的返回值是一個指標(即地址), 這種返回指標值的函式稱為指標型函式。定義指標型函式的一般形式為:型別說明符 *函式名(形參表){…… /*函式體*/}其中函式名之前加了“*”號表明這是一個指標型函式,即返回值是一個指標。型別說明符表示了返回的指標值所指向的資料型別。如:int *ap(int x,int y){......
/*函式體*/}  表示ap是一個返回指標值的指標型函式, 它返回的指標指向一個整型變數。下例中定義了一個指標型函式
day_name,它的返回值指向一個字串。該函式中定義了一個靜態指標陣列name。name
陣列初始化賦值為八個字串,分別表示各個星期名及出錯提示。形參n表示與星期名所對應的整數。在主函式中, 把輸入的整數i作為實參,
在printf語句中呼叫day_name函式並把i值傳送給形參 n。day_name函式中的return語句包含一個條件表示式, n
值若大於7或小於1則把name[0] 指標返回主函式輸出出錯提示字串“Illegal
day”。否則返回主函式輸出對應的星期名。主函式中的第7行是個條件語句,其語義是,如輸入為負數(i<0)則中止程式執行退出程式。exit是一個庫函式,exit(1)表示發生錯誤後退出程式,
exit(0)表示正常退出。  應該特別注意的是函式指標變數和指標型函式這兩者在寫法和意義上的區別。如int(*p)()和int
*p()是兩個完全不同的量。int(*p)()是一個變數說明,說明p 是一個指向函式入口的指標變數,該函式的返回值是整型量,(*p)的兩邊的括號不能少。int
*p() 則不是變數說明而是函式說明,說明p是一個指標型函式,其返回值是一個指向整型量的指標,*p兩邊沒有括號。作為函式說明,
在括號內最好寫入形式引數,這樣便於與變數說明區別。 對於指標型函式定義,int *p()只是函式頭部分,一般還應該有函式體部分。main(){int i;char *day_name(int n);printf("input Day
No:\n");scanf("%d",&i);if(i<0) exit(1);printf("Day
No:%2d-->%s\n",i,day_name(i));}char *day_name(int n){static char
*name[]={ "Illegal
day","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"};return((n<1 n>7)
? name[0] : name[n]);}  本程式是通過指標函式,輸入一個1~7之間的整數,
輸出對應的星期名。指標陣列的說明與使用一個數組的元素值為指標則是指標陣列。 指標陣列是一組有序的指標的集合。
指標陣列的所有元素都必須是具有相同儲存型別和指向相同資料型別的指標變數。  指標陣列說明的一般形式為: 型別說明符*陣列名[陣列長度]  其中型別說明符為指標值所指向的變數的型別。例如: int *pa[3] 表示pa是一個指標陣列,它有三個陣列元素,
每個元素值都是一個指標,指向整型變數。通常可用一個指標陣列來指向一個二維陣列。 指標陣列中的每個元素被賦予二維陣列每一行的首地址,
因此也可理解為指向一個一維陣列。圖6—6表示了這種關係。int
a[3][3]={1,2,3,4,5,6,7,8,9};int *pa[3]={a[0],a[1],a[2]};int
*p=a[0];main(){int
i;for(i=0;i<3;i++)printf("%d,%d,%d\n",a[i][2-i],*a[i],*(*(a+i)+i));for(i=0;i<3;i++)printf("%d,%d,%d\n",*pa[i],p[i],*(p+i));}  本例程式中,pa是一個指標陣列,三個元素分別指向二維陣列a的各行。然後用迴圈語句輸出指定的陣列元素。其中*a[i]表示i行0列元素值;*(*(a+i)+i)表示i行i列的元素值;*pa[i]表示i行0列元素值;由於p與a[0]相同,故p[i]表示0行i列的值;*(p+i)表示0行i列的值。讀者可仔細領會元素值的各種不同的表示方法。
應該注意指標陣列和二維陣列指標變數的區別。
這兩者雖然都可用來表示二維陣列,但是其表示方法和意義是不同的。  二維陣列指標變數是單個的變數,其一般形式中"(*指標變數名)"兩邊的括號不可少。而指標陣列型別表示的是多個指標(
一組有序指標)在一般形式中"*指標陣列名"兩邊不能有括號。例如: int
(*p)[3];表示一個指向二維陣列的指標變數。該二維陣列的列數為3或分解為一維陣列的長度為3。 int *p[3]
表示p是一個指標陣列,有三個下標變數p[0],p[1],p[2]均為指標變數。  指標陣列也常用來表示一組字串,
這時指標陣列的每個元素被賦予一個字串的首地址。 指向字串的指標陣列的初始化更為簡單。例如在例6.20中即採用指標陣列來表示一組字串。 其初始化賦值為:char *name[]={"Illagal
day","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"};  完成這個初始化賦值之後,name[0]即指向字串"Illegal
day",name[1]指?quot;Monday"......。  指標陣列也可以用作函式引數。在本例主函式中,定義了一個指標陣列name,並對name
作了初始化賦值。其每個元素都指向一個字串。然後又以name 作為實參呼叫指標型函式day name,在呼叫時把陣列名 name
賦予形參變數name,輸入的整數i作為第二個實參賦予形參n。在day
name函式中定義了兩個指標變數pp1和pp2,pp1被賦予name[0]的值(即*name),pp2被賦予name[n]的值即*(name+
n)。由條件表示式決定返回pp1或pp2指標給主函式中的指標變數ps。最後輸出i和ps的值。指標陣列作指標型函式的引數main(){static char
*name[]={ "Illegal
day","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"};char
*ps;int i;char *day_name(char *name[],int n);printf("input Day
No:\n");scanf("%d",&i);if(i<0)
exit(1);ps=day_name(name,i);printf("Day
No:%2d-->%s\n",i,ps);}char *day_name(char *name[],int n){char
*pp1,*pp2;pp1=*name;pp2=*(name+n);return((n<1 n>7)?
pp1:pp2);}下例要求輸入5個國名並按字母順序排列後輸出。在以前的例子中採用了普通的排序方法,
逐個比較之後交換字串的位置。交換字串的物理位置是通過字串複製函式完成的。 反覆的交換將使程式執行的速度很慢,同時由於各字串(國名)
的長度不同,又增加了儲存管理的負擔。 用指標陣列能很好地解決這些問題。把所有的字串存放在一個數組中,
把這些字元陣列的首地址放在一個指標陣列中,當需要交換兩個字串時,
只須交換指標陣列相應兩元素的內容(地址)即可,而不必交換字串本身。程式中定義了兩個函式,一個名為sort完成排序,
其形參為指標陣列name,即為待排序的各字串陣列的指標。形參n為字串的個數。另一個函式名為print,用於排序後字串的輸出,其形參與sort的形參相同。主函式main中,定義了指標陣列name
並作了初始化賦值。然後分別呼叫sort函式和print函式完成排序和輸出。值得說明的是在sort函式中,對兩個字串比較,採用了strcmp
函式,strcmp函式允許參與比較的串以指標方式出現。name[k]和name[ j]均為指標,因此是合法的。字串比較後需要交換時,
只交換指標陣列元素的值,而不交換具體的字串, 這樣將大大減少時間的開銷,提高了執行效率。現程式設計如下:#include"string.h"main(){void sort(char *name[],int
n);void print(char *name[],int n);static char *name[]={
"CHINA","AMERICA","AUSTRALIA","FRANCE","GERMAN"};int
n=5;sort(name,n);print(name,n);}void sort(char *name[],int
n){char *pt;int
i,j,k;for(i=0;i 0)
k=j;if(k!=i){pt=name[i];name[i]=name[k];name[k]=pt;}}}void
print(char *name[],int n){int i;for (i=0;i printf("%s\n",name[i]);}main函式的引數  前面介紹的main函式都是不帶引數的。因此main
後的括號都是空括號。實際上,main函式可以帶引數,這個引數可以認為是 main函式的形式引數。C語言規定main函式的引數只能有兩個,
習慣上這兩個引數寫為argc和argv。因此,main函式的函式頭可寫為: main
(argc,argv)C語言還規定argc(第一個形參)必須是整型變數,argv(
第二個形參)必須是指向字串的指標陣列。加上形參說明後,main函式的函式頭應寫為:main
(argc,argv)int argv;char *argv[];或寫成:main (int argc,char
*argv[])  由於main函式不能被其它函式呼叫, 因此不可能在程式內部取得實際值。那麼,在何處把實參值賦予main函式的形參呢?
實際上,main函式的引數值是從作業系統命令列上獲得的。當我們要執行一個可執行檔案時,在DOS提示符下鍵入檔名,再輸入實際引數即可把這些實參傳送到main的形參中去。  DOS提示符下命令列的一般形式為:
C:\>可執行檔名 引數 引數……; 但是應該特別注意的是,main
的兩個形參和命令列中的引數在位置上不是一一對應的。因為,main的形參只有二個,而命令列中的引數個數原則上未加限制。argc引數表示了命令列中引數的個數(注意:檔名本身也算一個引數),argc的值是在輸入命令列時由系統按實際引數的個數自動賦予的。例如有命令列為:
C:\>E6 24 BASIC dbase FORTRAN由於檔名E6
24本身也算一個引數,所以共有4個引數,因此argc取得的值為4。argv引數是字串指標陣列,其各元素值為命令列中各字串(引數均按字串處理)的首地址。
指標陣列的長度即為引數個數。陣列元素初值由系統自動賦予。其表示如圖6.8所示:main(int
argc,char
*argv){while(argc-->1)printf("%s\n",*++argv);}本例是顯示命令列中輸入的引數如果上例的可執行檔名為e24.exe,存放在A驅動器的盤內。因此輸入的命令列為:
C:\>a:e24 BASIC dBASE FORTRAN則執行結果為:BASICdBASEFORTRAN  該行共有4個引數,執行main時,argc的初值即為4。argv的4個元素分為4個字串的首地址。執行while語句,每迴圈一次
argv值減1,當argv等於1時停止迴圈,共迴圈三次, 因此共可輸出三個引數。在printf函式中,由於列印項*++argv是先加1再列印,
故第一次列印的是argv[1]所指的字串BASIC。第二、
三次迴圈分別列印後二個字串。而引數e24是檔名,不必輸出。  下例的命令列中有兩個引數,第二個引數20即為輸入的n值。在程式中*++argv的值為字串“20”,然後用函式"atoi"把它換為整型作為while語句中的迴圈控制變數,輸出20個偶數。#include"stdlib.h"main(int argc,char*argv[]){int
a=0,n;n=atoi(*++argv);while(n--) printf("%d
",a++*2);}  本程式是從0開始輸出n個偶數。指向指標的指標變數如果一個指標變數存放的又是另一個指標變數的地址,
則稱這個指標變數為指向指標的指標變數。  在前面已經介紹過,通過指標訪問變數稱為間接訪問,
簡稱間訪。由於指標變數直接指向變數,所以稱為單級間訪。 而如果通過指向指標的指標變數來訪問變數則構成了二級或多級間訪。在C語言程式中,對間訪的級數並未明確限制,
但是間訪級數太多時不容易理解解,也容易出錯,因此,一般很少超過二級間訪。指向指標的指標變數說明的一般形式為:型別說明符** 指標變數名;例如: int ** pp;
表示pp是一個指標變數,它指向另一個指標變數, 而這個指標變數指向一個整型量。下面舉一個例子來說明這種關係。main(){int
x,*p,**pp;x=10;p=&x;pp=&p;printf("x=%d\n",**pp);}  上例程式中p 是一個指標變數,指向整型量x;pp也是一個指標變數,
它指向指標變數p。通過pp變數訪問x的寫法是**pp。程式最後輸出x的值為10。通過上例,讀者可以學習指向指標的指標變數的說明和使用方法。  下述程式中首先定義說明了指標陣列ps並作了初始化賦值。
又說明了pps是一個指向指標的指標變數。在5次迴圈中, pps
分別取得了ps[0],ps[1],ps[2],ps[3],ps[4]的地址值(如圖6.10所示)。再通過這些地址即可找到該字串。main(){static char *ps[]={
"BASIC","DBASE","C","FORTRAN","PASCAL"};char **pps;int
i;for(i=0;i<5;i++){pps=ps+i;printf("%s\n",*pps);}}本程式是用指向指標的指標變數程式設計,輸出多個字串。本章小結1.
指標是C語言中一個重要的組成部分,使用指標程式設計有以下優點:(1)提高程式的編譯效率和執行速度。(2)通過指標可使用主調函式和被調函式之間共享變數或資料結構,便於實現雙向資料通訊。(3)可以實現動態的儲存分配。(4)便於表示各種資料結構,編寫高質量的程式。2.
指標的運算(1)取地址運算子&:求變數的地址(2)取內容運算子*:表示指標所指的變數(3)賦值運算·把變數地址賦予指標變數·同類型指標變數相互賦值·把陣列,字串的首地址賦予指標變數·把函式入口地址賦予指標變數(4)加減運算對指向陣列,字串的指標變數可以進行加減運算,如p+n,p-n,p++,p--等。對指向同一陣列的兩個指標變數可以相減。對指向其它型別的指標變數作加減運算是無意義的。(5)關係運算指向同一陣列的兩個指標變數之間可以進行大於、小於、 等於比較運算。指標可與0比較,p==0表示p為空指標。3.
與指標有關的各種說明和意義見下表。int *p;     p為指向整型量的指標變數int *p[n];
  p為指標陣列,由n個指向整型量的指標元素組成。int (*p)[n];  p為指向整型二維陣列的指標變數,二維陣列的列數為nint *p()
   p為返回指標值的函式,該指標指向整型量int (*p)()   p為指向函式的指標,該函式返回整型量int **p    
p為一個指向另一指標的指標變數,該指標指向一個整型量。4.
有關指標的說明很多是由指標,陣列,函式說明組合而成的。但並不是可以任意組合,例如陣列不能由函式組成,即陣列元素不能是一個函式;函式也不能返回一個數組或返回另一個函式。例如int
a[5]();就是錯誤的。5. 關於括號在解釋組合說明符時,
識別符號右邊的方括號和圓括號優先於識別符號左邊的“*”號,而方括號和圓括號以相同的優先順序從左到右結合。但可以用圓括號改變約定的結合順序。6.
閱讀組合說明符的規則是“從裡向外”。從識別符號開始,先看它右邊有無方括號或園括號,如有則先作出解釋,再看左邊有無*號。
如果在任何時候遇到了閉括號,則在繼續之前必須用相同的規則處理括號內的內容。例如:int*(*(*a)())[10]↑ ↑↑↑↑↑↑7
6 4 2 1 3
5上面給出了由內向外的閱讀順序,下面來解釋它:(1)識別符號a被說明為;(2)一個指標變數,它指向;(3)一個函式,它返回;(4)一個指標,該指標指向;(5)一個有10個元素的陣列,其型別為;(6)指標型,它指向;(7)int型資料。因此a是一個函式指標變數,該函式返回的一個指標值又指向一個指標陣列,該指標陣列的元素指向整型量。

輕鬆學會C語言 (共13篇) 上一篇:第六章:指標 下一篇:第七章:結構與聯...

函式, 變數, 指標, 字串, 陣列,
相關問題答案