在這裏我們關於指針討論一下幾個:
指針數組 數組指針 函數指針 函數指針數組 指向函數指針數組的指針
接下來,用一些例子來進行形象說明:
1.指針數組: 是數組,是一個存放指針的數組;
int *arr1[10];
int *arr2[4];
int **arr3[5];
2.數組指針:是指針,該指針有能力指向一個數組;
int (*p)[10];
上面代碼解釋:p是先和*結合的,說明p是一個指針變量,然後指向的是一個大小爲10個整型的數組,所以說p是一個指針,指向一個數組,叫數組指針;
注意:[]的優先級高於*,所以必須加上()來保證p先和*結合.
3.函數指針:是指針,該指針有能力指向一個函數;
用一段代碼對函數指針進行說明:
#include <stdio.h>
void test()
{
printf("hehe\n");
}
int main()
{
void(*Pfun)() = test;
Pfun();
return 0;
}
函數也有自己的地址,函數名就是函數的地址,對函數名進行取地址也行(&函數名).
如上述代碼,將test函數的地址賦值給Pfun,間接打印出test函數的內容.
在函數中*是沒有意義的,如(*Pfun)();是等價於Pfun();.
再例如:
#include <stdio.h>
int Add(int x,int y)
{
return x + y;
}
int main()
{
int(*Pfun)(int, int) = Add;
printf("%d\n", Pfun(1, 2));
return 0;
}
上述代碼中,Pfun可存放函數的地址,Pfun先和*結合,說明Pfun是一個指針,指針指向的是一個函數,指向函數的參數類型爲int,int,返回值類型爲int.接下來看看兩段有趣的代碼:
代碼1:
(*(void (*)())0)();
(void (*)())0是對零地址處的函數進行強制類型轉換,轉換成函數指針類型,總體來說還是函數指針;
代碼2:
void (*signal(int,void (*)(int)))(int);
對上述代碼的來說,signal是一個函數的聲明,該函數的第一個參數類型是int,第二個參數類型是一個函數指針,該指針能夠指向一個參數類型爲int,返回值類型爲void的函數,signal函數的返回類型也是一個函數指針,該指針能夠指向一個參數類型爲int,返回值類型爲void的函數.
4.函數指針數組:把函數的地址存到一個數組中,把這個數組叫做函數指針數組;
int (*parr[10])();
對上述代碼來說,parr先和[]結合,說明parr是一個數組,數組的內容是類型爲int (*)()的函數指針。
函數指針的類型一般用於轉移表。
函數聲明可以沒有形參名,但定義一定要有。
5.指向函數指針數組的指針;
指向函數指針數組的指針是一個指針,指針指向一個數組,數組的元素都是函數指針。
void test(const char *str)
{
printf("%s\n",str);
}
int main()
{
char *str = "abcd";
void(*Pfun)(const char *) = test;
void (*PfunArr[5])(const char *str);
PfunArr[0] = test;
void(*((PPfunArr[5])(const char *)) = &PfunArr;
return 0;
}
void(*Pfun)(const char *) = test;函數指針Pfun;
void (*PfunArr[5])(const char *str);函數指針的數組PfunArr;
void(*((PPfunArr[5])(const char *)) = &PfunArr;
——〉指向函數指針數組PfunArr的指針ppfunArr;