目錄
前言:
一、函數指針變量的概念
二、函數指針變量的創建
三、函數指針變量的使用
四、兩段特殊代碼的理解
五、typedef
六、函數指針數組
總結:
前言:
? ? ? ? 本文主要講述C語言指針中的函數指針,包括函數指針變量的概念、創建及使用。兩段特殊代碼的理解,typedef關鍵字的使用,以及函數指針數組的使用,最后還有一個代碼案例--計算器的實現。希望對大家有所幫助。
一、函數指針變量的概念
函數指針變量,是用于存儲函數地址的指針變量
那么,函數有地址嗎?函數名與地址有關嗎?
簡單測試一下:
我們發現:函數名和取地址函數名得到的地址是一樣的
函數名本身可以被視為一個地址,指向函數代碼的起始位置,這與&函數名一樣,使用起來并無區別
二、函數指針變量的創建
既然函數名和&函數名得到了函數的地址,我們要存儲這種地址,就需要創建函數指針變量
定義語法:函數返回類型(*變量名)(形參類型,形參類型)
如:
觀察類型我們可以得知,函數指針變量的類型就是:去掉變量名,剩下的就是函數指針變量的類型
函數指針類型解析:
int? (*pf4) (int x, int y)
- int:pf4指向的函數類型
- pf4:函數指針變量名,*表明其為指針變量
- (int x, int y):pf4指向函數的參數類型和個數的交代
三、函數指針變量的使用
通過函數指針調用指針指向的函數
使用方法1:
該方法就是通過解引用指針,找到函數地址,然后傳入參數,接收返回值
使用方法2:
直接寫函數指針變量的變量名,然后傳入參數,這與直接寫函數名傳入參數是一樣的,因為該指針變量值就等于函數名的地址
其實方法1中,*pf前面的*號本身無實際作用
我們無論寫多少*號,結果是一樣的,編譯器沒有對這個符號進行相關操作,故相當于擺設了,不過為了提高可讀性,一般是寫一個*號
注意:*pf必須用括號括起來,因為左邊優先級高于*號,不加括號會被編譯器認為是解引用函數的返回值,而這是一個非法訪問
四、兩段特殊代碼的理解
1.( *(? void (*)()? ) 0 ) ()
請問這段代碼是什么意思?
這其實是一次函數調用的代碼,調用0地址處的函數
那么如何分析這段代碼呢,我們畫圖來理解:
注意:該代碼出自《C陷阱與缺陷》一書,情景是一位程序員需要寫一個獨立運行于某種微處理器上的C程序,當計算機啟動時,硬件將調用0地址處的子例程(函數)。于是設計出了這段代碼
2.void ( *signal( int , void(*)(int) ) )(int);
請問這段代碼是什么意思?
答案是:這是一個函數聲明。我們畫圖分析
以上難以理解的可能就是第3步,按照以往的理解,理論上函數的返回類型不應該寫在函數名前面嗎,也就是下面這樣
我們發現把 void(*)(int) 的返回類型寫在函數名前面,編譯器報錯了
這其實是語法規定的,函數指針作為返回類型,函數名需寫在類型的里面,也就是*號的旁邊,上面那種才是正確的寫法
五、typedef
我們發現上面那段代碼是不是較難看懂,如果能讓其與一般函數寫法一樣,也就是函數返回類型寫在前面就好了,這里就有一個方法,使用typedef重命名
typedef:對類型名進行重命名
例1:重命名unsigned int
例2:重命名數組指針
注意:數組指針重命名,重命名的名字要放在括號里邊
現在,就讓我們把void ( *signal( int , void(*)(int) ) )(int)進行重命名:
注意:與數組指針一樣,我們重命名的名字要放在類型里面,之后我們不管是以返回類型寫在函數名前面,還是以函數參數類型寫在參數里都可以,這樣看代碼是不是明朗了許多
六、函數指針數組
函數指針數組:存儲函數指針的數組,數組的元素都是一個個類型相同的函數指針
定義語法:見下面第二張圖
例如:
如上,兩個相同類型的函數指針變量我們可以定義,可是當相同類型的函數多起來后,如果我們需要儲存這些函數的地址,就需要數組來接收才方便了。
如:
注意:定義函數指針數組,數組放在數組類型里邊
調用數組元素時,就正常使用下標+傳入參數即可
如果覺得以上內容簡單,我們可以實現一個簡單案例
簡單計算器的實現:
#include <stdio.h>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;
}void menu()
{printf("***************************************\n");printf("********** 1.Add 2.Sub **********\n");printf("********** 3.Mul 4.Div **********\n");printf("********** 0.exit **********\n");printf("***************************************\n");
}int main()
{int(*pf_arr[5])(int, int) = { 0,Add,Sub,Mul,Div };int input = 0;do{menu();printf("請選擇:\n");scanf("%d", &input);if (input >= 1 && input <= 4){int a = 0;int b = 0;printf("請輸入兩個整數:\n");scanf("%d %d", &a, &b);printf("%d\n", pf_arr[input](a, b));}else if (input == 0){printf("程序退出\n");break;}else{printf("選擇錯誤,請重新選擇:\n");}} while (input);return 0;
}
總結:
????????以上就是本文的全部內容了,希望對大家有所幫助,哪里有問題歡迎提出,感謝大家的支持