文章目錄
- 函式指標
- 函式指標陣列
- 指向函式指標陣列的指標
- 結束語
函式指標
先看一段代碼
int Add(int x, int y)
{
return x + y;
}
int main()
{
printf("%p\n", &Add);
printf("%p\n", Add);
return 0;
}
輸出結果如下

從上我們可以了解到其實函式名就是一個地址,所以用不用&的結果是一樣的,但是地址該如何保存下來呢?
這就涉及到函式指標了,看代碼
void test()
{
printf("hehe\n");
}
下面pfun1和pfun2哪個有能力存放test函式的地址?
void (*pfun1)();
void *pfun2();
pfun1可以存放,pfun1先和*結合,說明pfun1是指標,指標指向的是一個函式,指向的函式無 引數,回傳值型別為void,
實際例子如下:
int Add(int x, int y)
{
return x + y;
}
int main()
{
int (*pf)(int, int) = Add;
//pf是一個函式指標,該指標指向的是一個函式,指向的函式有兩個整形引數,回傳值型別為int,
printf("%d\n", (*pf)(1, 2));
printf("%d\n", pf(1, 2));
return 0;
}
輸出結果如下

上面說到,既然函式就是用地址來實作功能的,那么我們解參考和不解參考產生的結果當然是一樣的,
我們接著來讀讀下面這個兩個代碼
//代碼1
(*(void (*)())0)();
//代碼2
void (*signal(int , void(*)(int)))(int);
//代碼1
(*(void (*)())0)();
我們先將(*(void (*)())0)()進行拆分
(*( )0)()
void(*)()
void(*)()不就是函式指標嘛,該指標指向一個函式,無引數,回傳型別為void
那么void(*)()0?是什么意思呢
我們先來了解這個玩意兒(float*)p,p是一個指標,那么這個的意思就是把p強制型別轉化為(float*)
回到void(*)()0,它的意思也很簡單,就是把0這個整形強制轉化為函式指標型別,地址為0,
那么解參考他就是找到這個0地址的內容,是一個函式,無引數,回傳型別為void,
即為(*(void (*)())0)(),
示例如下
int test()
{
printf("QQHSJ\n");
return 0;
}
int main()
{
test();
printf("%p\n", test);
(*(int(*)())test)();
return 0;
}
輸出結果如下

//代碼2
void (*signal(int, void(*)(int)))(int);
它實際上就是一個函式宣告,跟代碼1一樣我們來進行拆分
void(* )(int);
signal(int, void(*)(int))
我們先看void(*p)(int),p是一個函式指標,它指向一個函式,引數為int,回傳值型別為void,
一般來說我們通常的函式宣告是這樣的
int Add(int, int);
所以跟上述幾乎代碼2幾乎是一樣的,如果實在看不明白,我們就用一種別扭的方式理解,當然了這樣的寫法在編譯器上面是無法通過的,
void(*)(int) signal(int, void(*)(int));
與
int Add(int, int);
對比來看,形式完全是一模一樣,所以它完完全全就是一個函式宣告,只是回傳型別是函式指標型別
就好比這個
int* BALABALA(int,int);,回傳型別是整形指標型別,
但是void(*)(int) signal(int, void(*)(int));這種形式是可以實作的,但是需要用到typedef
如下
typedef void(*pfun_t)(int);
pfun_t signal(int, pfun_t);
函式指標陣列
陣列是一個存放相同型別資料的存盤空間,那我們已經學習了指標陣列, 比如:
int *arr[10];
//陣列的每個元素是int*
那要把函式的地址存到一個陣列中,那這個陣列就叫函式指標陣列,那函式指標的陣列如何定義呢?
int (*parr1[10])();
parr1 先和 [] 結合,說明parr1是陣列,陣列的內容是什么呢? 是 int (*)() 型別的函式指標,
如果覺得還不明確,用typedef替換
typedef int(* pfun_int)();
pfun_int parr1[10];
這樣是不是清楚多了,
具體應用如下,加減乘除的計算代碼
int Add(int x, int y)
{
return x + y;
}
int Sub(int x, int y)
{
return x - y;
}
int Mul(int x, int y)
{
return x * y;
}
int Div(int x, int y)
{
return x / y;
}
int main()
{
int x, y;
int input = 1;
int ret = 0;
int(*p[5])(int x, int y) = {0, Add, Sub, Mul, Div }; //轉移表
while (input)
{
printf("**************************\n");
printf("**1:add************2:sub**\n");
printf("**3:mul************4:div**\n");
printf("**************************\n");
printf("請選擇:");
scanf("%d", &input);
if ((input <= 4 && input >= 1))
{
printf("輸入運算元:");
scanf("%d %d", &x, &y);
ret = (*p[input])(x, y);
}
else
printf("輸入有誤\n");
printf("ret = %d\n", ret);
}
return 0;
}
指向函式指標陣列的指標
真是越走越遠啊,難度確實蠻大的,大家好好學吧,柒柒沒辦法講清楚的話,還望大家多抽點時間去看看書或者視頻,
指向函式指標陣列的指標是一個指標,指標指向一個陣列 ,陣列的元素都是函式指標 ;
看代碼
void test(const char* str)
{
printf("%s\n", str);
}
int main()
{
//函式指標pfun
void (*Pfun)(const char*) = test;
//函式指標的陣列PfunArr
void (*PfunArr[5])(const char*);
pfunArr[0] = test;
//指向函式指標陣列PfunArr的指標PPfunArr
void (*(*PPfunArr)[5])(const char*) = &PfunArr;
return 0;
}
大家可能對第三個抱有非常大的疑問,解釋如下
其實我們依舊可以用typedef的方式替換,從而理解“指向 函式指標陣列 的 指標”
typedef void(*Void_Char)(const char*)
Void_Char PfunArr[5]
Void_Char PfunArr[5]它的意思就是PfunArr是一個陣列,它的型別為Void_Char,
我們再回憶一下陣列指標是怎么定義的
int arr[5] = { 0 };
int (*p)[5] = &arr
那么要實作指標指向這個陣列是不是變得例外簡單了,即為
Void_Char *PPfunArr[5] = &PfunArr;
這樣看是不是清楚很多了,我們再將它展開不就得到了void (*(*PPfunArr)[5])(const char*) = &PfunArr;
結束語
關于這一部分,可能還要小小的地方沒有繼續擴展,即回呼函式和指標和陣列的決議
回呼函式,我會專門詳細的寫一段代碼,配上注釋的情況下供小伙伴們閱讀,
指標和陣列的決議,部分代碼如下,大家可以想想它輸出的結果如何?
int a[] = {1,2,3,4};
printf("%d\n",sizeof(a));
printf("%d\n",sizeof(a+0));
printf("%d\n",sizeof(*a));
printf("%d\n",sizeof(a+1));
printf("%d\n",sizeof(a[1]));
printf("%d\n",sizeof(&a));
printf("%d\n",sizeof(*&a));
printf("%d\n",sizeof(&a+1));
printf("%d\n",sizeof(&a[0]));
printf("%d\n",sizeof(&a[0]+1));
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr+0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr+1));
printf("%d\n", sizeof(&arr[0]+1));
printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr+0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr+1));
printf("%d\n", strlen(&arr[0]+1));
歡迎大家共同探討,如有什么不對的地方也請大家指出哦~
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/280292.html
標籤:其他
