往往,我們一提到指標函式和函式指標的時候,就有很多人弄不懂。下面就由南寧達內小編詳細為大家介紹C語言中指標函式和函式指標。
一、指標函式
當一個函式宣告其返回值為一個指標時,實際上就是返回一個地址給呼叫函式,以用於需要指標或地址的表示式中。
格式:
型別說明符 * 函式名(引數)
當然了,由於返回的是一個地址,所以型別說明符一般都是int。
例如:
int *GetDate(); int * aaa(int,int);
函式返回的是一個地址值,經常使用在返回陣列的某一元素地址上。
int * GetDate(int wk,int dy); main()
{ int wk,dy;
do { printf("Enter week(1-5)day(1-7)\n"); scanf("%d%d",&wk,&dy);
} while(wk<1 wk>5 dy<1 dy>7);
printf("%d\n",*GetDate(wk,dy)); }
int * GetDate(int wk,int dy) {
static int calendar[5][7]= {
{1,2,3,4,5,6,7}, {8,9,10,11,12,13,14},
{15,16,17,18,19,20,21}, {22,23,24,25,26,27,28},
{29,30,31,-1} };
return &calendar[wk-1][dy-1]; }
程式應該是很好理解的,子函式返回的是陣列某元素的地址。輸出的是這個地址裡的值。
二、函式指標
指向函式的指標包含了函式的地址,可以通過它來呼叫函式。宣告格式如下:
型別說明符 (*函式名)(引數)
其實這裡不能稱為函式名,應該叫做指標的變數名。這個特殊的指標指向一個返回整型值的函式。指標的宣告筆削和它指向函式的宣告保持一致。
指標名和指標運算子外面的括號改變了預設的運算子優先順序。如果沒有圓括號,就變成了一個返回整型指標的函式的原型宣告。
例如:
void (*fptr)();
把函式的地址賦值給函式指標,可以採用下面兩種形式:
fptr=&Function; fptr=Function;
取地址運算子&不是必需的,因為單單一個函式識別符號就標號表示了它的地址,如果是函式呼叫,還必須包含一個圓括號括起來的引數表。可以採用如下兩種方式來通過指標呼叫函式:
x=(*fptr)(); x=fptr();
第二種格式看上去和函式呼叫無異。但是有些程式設計師傾向於使用第一種格式,因為它明確指出是通過指標而非函式名來呼叫函式的。下面舉一個例子:
void (*funcp)(); void FileFunc(),EditFunc();
main() {
funcp=FileFunc; (*funcp)();
funcp=EditFunc; (*funcp)();
} void FileFunc()
{ printf("FileFunc\n");
} void EditFunc()
{ printf("EditFunc\n"); }
程式輸出為:
FileFunc EditFunc
三、指標的指標
指標的指標看上去有些令人費解。它們的宣告有兩個星號。例如:
char ** cp;
如果有三個星號,那就是指標的指標的指標,四個星號就是指標的指標的指標的指標,依次類推。當你熟悉了簡單的例子以後,就可以應付複雜的情況了。當然,實際程式中,一般也只用到二級指標,三個星號不常見,更別說四個星號了。
指標的指標需要用到指標的地址。
char c='A'; char *p=&c; char **cp=&p;
通過指標的指標,不僅可以訪問它指向的指標,還可以訪問它指向的指標所指向的資料。
下面就是幾個這樣的例子:
char *p1=*cp; char c1=**cp;
你可能想知道這樣的結構有什麼用。利用指標的指標可以允許被呼叫函式修改區域性指標變數和處理指標陣列。
void FindCredit(int **); main()
{ int vals[]={7,6,5,-4,3,2,1,0};
int *fp=vals; FindCredit(&fp);
printf("%d\n",*fp); }
void FindCredit(int ** fpp) {
while(**fpp!=0) if(**fpp<0) break;
else (*fpp)++; }
首先用一個數組的地址初始化指標fp,然後把該指標的地址作為實參傳遞給函式FindCredit()。FindCredit()函式通過表示式**fpp間接地得到陣列中的資料。為遍歷陣列以找到一個負值,FindCredit()函式進行自增運算的物件是呼叫者的指向陣列的指標,而不是它自己的指向呼叫者指標的指標。語句(*fpp)++就是對形參指標指向的指標進行自增運算的。但是因為*運算子高於++運算子,所以圓括號在這裡是必須的,如果沒有圓括號,那麼++運算子將作用於二重指標fpp上。
四、指向指標陣列的指標
指標的指標另一用法舊處理指標陣列。有些程式設計師喜歡用指標陣列來代替多維陣列,一個常見的用法就是處理字串。
char *Names[]= {
"Bill", "Sam",
"Jim", "Paul",
"Charles", 0
};
main() { char **nm=Names; while(*nm!=0) printf("%s\n",*nm++);
}
先用字元型指標陣列Names的地址來初始化指標nm。每次printf()的呼叫都首先傳遞指標nm指向的字元型指標,然後對nm進行自增運算使其指向陣列的下一個元素(還是指標)。注意完成上述認為的語法為*nm++,它首先取得指標指向的內容,然後使指標自增。