天天看點

深入了解 [指針函數] 、[函數指針]、[指針的指針]、[指向指針數組的指針]

指針函數

1、指針函數是指帶指針的函數,即本質是一個函數。當一個函數聲明其傳回值為一個指針時,實際上就是傳回一個位址給調用函數,以用于需要指針或位址的表達式中。

函數傳回類型是某一類型的指針:

格式:

類型辨別符  *函數名(參數表)

int *match(void *key_x,void *key_y);

解析:首先來說它是一個函數,隻不過這個函數的傳回值是一個位址值。函數傳回值必須用同類型的指針變量來接受,也就是說,指針函數一定有函數傳回值,而且,在主調函數中,函數傳回值必須賦給同類型的指針變量。

例如:

float *match();

float *p;

p = match(a);

重要知識點:

注意指針函數與函數指針表示方法不同,千萬不要混淆。最簡單的辨識方式就是看函數名前面的指針*号有沒有被括号()包含,如果被包含就是函數指針,反之則是指針函數。

指針函數

2、函數指針是指向函數的指針變量,即本質是一個指針變量。

函數指針三指向可執行代碼段或調用可執行代碼段的資訊塊的指針,而不是指向某種資料的指針。函數指針将函數當作普通的資料那樣存儲和管理。

格式如下:

類型說明符 (*函數名)(參數)

int (*match) (int x);

int *f = match;

PS:

其實這裡不能稱為函數名,應該叫做指針的變量名。這個特殊的指針指向一個傳回整型值的函數。指針的聲明必須和它指向函數的聲明保持一緻。

指針名和指針運算符外面的括号改變了預設的運算符優先級。如果沒有圓括号,就變成了一個傳回整型指針的函數的原型聲明。

例如:

void (*fptr)();

把函數的位址指派給函數指針,可以采用下面兩種形式:

   fptr = &Function;

   fptr = Function;

取位址運算符&不是必需的,因為單單一個函數辨別符就标号表示了它的位址,如果是函數調用,還必須包含一個圓括号括起來的參數表。

可以采用如下兩種方式來通過指針調用函數:

 x = (*fptr)();

     x = fptr();

第二種格式看上去和函數調用無異。但是推薦使用第一種格式,因為它明确指出是通過指針而非函數名來調用函數的。

函數指針和指針函數最主要的差別是一個是指針變量,一個是函數。

指針的指針 

三、指針的指針

例如:

    char ** data;

如果有三個星号,那就是指針的指針的指針,四個星号就是指針的指針的指針的指針,依次類推。當你熟悉了簡單的例子以後,就可以應付複雜的情況了。在實際程式中,一般也隻用到二級指針,三級指針和四級指針就很少用啦。

指針的指針需要用到指針的位址。

    char c = 'A';

    char *p = &c;

    char **data= &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[]=
{
     zhangsan,
     lisi,
      wangwu,
      maliu,
      fu,
      0
     };

main()
{
  char **nm=Names;
  while(*nm!=0) 
  printf(%s\n,*nm++);
}
           

先用字元型指針數組Names的位址來初始化指針nm。每次printf()的調用都首先傳遞指針nm指向的字元型指針,然後對nm進行自增運算使其指向數組的下一個元素(還是指針)。注意完成上述認為的文法為*nm++,它首先取得指針指向的内容,然後使指針自增。

數組中的最後一個元素被初始化為0,while循環一次來判斷是否到了數組末尾。具有零值的指針常常被用做循環數組的終止符。其中零值指針為空指針(NULL)。

繼續閱讀