深入解析C++中函數(shù)指針及其數(shù)組、typedef關(guān)鍵字用法舉例
一、函數(shù)指針變量的創(chuàng)建
1、什么是函數(shù)指針變量?
類(lèi)比整型指針和數(shù)組指針的概念,我們可以得出:函數(shù)指針變量是用來(lái)存放函數(shù)地址的變量,通過(guò)這個(gè)地址我們可以調(diào)用相應(yīng)的函數(shù)。
2、函數(shù)是否有地址?
通過(guò)以下測(cè)試代碼可以驗(yàn)證:
#include <stdio.h>
void test() {
printf("hehe\n");
}
int main() {
printf("test: %p\n", test);
printf("&test: %p\n", &test);
return 0;
}輸出結(jié)果:

結(jié)果表明函數(shù)確實(shí)有地址,且函數(shù)名就是函數(shù)的地址,也可以通過(guò)&函數(shù)名的方式獲取函數(shù)地址。(重點(diǎn)!?。。?/span>
3、創(chuàng)建函數(shù)指針變量
函數(shù)指針變量的聲明語(yǔ)法與數(shù)組指針類(lèi)似:
void test() {
printf("hehe\n");
}
// 兩種等效的函數(shù)指針聲明方式
void (*pf1)() = &test;
void (*pf2)() = test;
int Add(int x, int y) {
return x + y;
}
// 函數(shù)指針聲明,參數(shù)名可省略
int (*pf3)(int, int) = Add;
int (*pf4)(int x, int y) = &Add;4、函數(shù)指針類(lèi)型解析
以int (*pf3)(int x, int y)為例:int (*) (int x, int y) 為pf3函數(shù)指針變量的類(lèi)型

二、函數(shù)指針變量的使用
通過(guò)函數(shù)指針調(diào)用函數(shù)的示例:
#include <stdio.h>
int Add(int x, int y) {
return x + y;
}
int main() {
int(*pf)(int, int) = Add;
// 兩種等效的調(diào)用方式
printf("%d\n", (*pf)(2, 3)); // 顯式解引用
printf("%d\n", pf(3, 5)); // 隱式調(diào)用
return 0;
}輸出結(jié)果:

三、兩段有趣的代碼
以下兩段有趣的代碼出自《C陷阱和缺陷》:
1、解釋(*(void (*)())0)();
這段代碼的功能是:調(diào)用位于內(nèi)存地址0處的函數(shù)。
讓我們逐步解析:
void (*)():這是一個(gè)函數(shù)指針類(lèi)型,表示"指向一個(gè)沒(méi)有參數(shù)且返回void的函數(shù)的指針"。(void (*)())0:將整數(shù)值0強(qiáng)制轉(zhuǎn)換為上述函數(shù)指針類(lèi)型。這表示"把地址0當(dāng)作一個(gè)函數(shù)的地址"。*(void (*)())0:解引用這個(gè)函數(shù)指針,得到位于地址0處的函數(shù)。(*(void (*)())0)():最后調(diào)用這個(gè)函數(shù)(通過(guò)函數(shù)指針調(diào)用)。
實(shí)際意義:這段代碼嘗試調(diào)用內(nèi)存地址0處的函數(shù)。在嵌入式系統(tǒng)中,這可能是調(diào)用復(fù)位向量或啟動(dòng)代碼的方式。但在大多數(shù)現(xiàn)代操作系統(tǒng)中,這會(huì)引發(fā)段錯(cuò)誤(segmentation fault),因?yàn)榈刂?通常是被保護(hù)的區(qū)域。
2、解釋void (*signal(int, void(*)(int)))(int);
這是一個(gè)函數(shù)聲明,聲明了名為signal的函數(shù)。讓我們分解它:
- 最內(nèi)層:
void(*)(int):這是一個(gè)函數(shù)指針類(lèi)型,表示"指向一個(gè)接受int參數(shù)且返回void的函數(shù)的指針"。 signal(int, void(*)(int)):signal是一個(gè)函數(shù),它接受兩個(gè)參數(shù):一個(gè)int、一個(gè)上述類(lèi)型的函數(shù)指針- 整個(gè)聲明:
void (*signal(int, void(*)(int)))(int):表示signal函數(shù)返回一個(gè)函數(shù)指針,這個(gè)指針指向"接受int參數(shù)且返回void的函數(shù)"。
更易讀的寫(xiě)法(使用typedef,下面會(huì)講解):
typedef void (*sighandler_t)(int); // 定義函數(shù)指針類(lèi)型 sighandler_t signal(int signum, sighandler_t handler);
實(shí)際意義:這是Unix/Linux系統(tǒng)中用于設(shè)置信號(hào)處理器的標(biāo)準(zhǔn)函數(shù)聲明。它:
- 接受一個(gè)信號(hào)編號(hào)(int)和一個(gè)處理該信號(hào)的函數(shù)指針
- 返回之前為該信號(hào)設(shè)置的處理函數(shù)指針
四、typedef關(guān)鍵字
typedef用于類(lèi)型重命名,可以簡(jiǎn)化復(fù)雜類(lèi)型的聲明。
1、基本用法
typedef unsigned int uint; // 將unsigned int重命名為uint typedef int* ptr_t; // 將int*重命名為ptr_t
2、對(duì)于數(shù)組指針和函數(shù)指針的重命名
新的類(lèi)型名必須在*的右邊:
typedef int(*parr_t)[5]; // 將數(shù)組指針類(lèi)型int(*)[5]重命名為parr_t typedef void(*pfun_t)(int); // 將函數(shù)指針類(lèi)型void(*)(int)重命名為pfun_t
3、使用typedef簡(jiǎn)化代碼void (*signal(int, void(*)(int)))(int);
typedef void(*pfun_t)(int); pfun_t signal(int, pfun_t);
五、函數(shù)指針數(shù)組
數(shù)組是存放相同類(lèi)型數(shù)據(jù)的存儲(chǔ)空間。我們已經(jīng)學(xué)過(guò)指針數(shù)組:
int *arr[10]; // 數(shù)組的每個(gè)元素是int*
如果要存儲(chǔ)函數(shù)地址,就需要使用函數(shù)指針數(shù)組。函數(shù)指針數(shù)組的定義方式:
int (*parr1[3])(); // 正確:包含3個(gè)函數(shù)指針的數(shù)組,每個(gè)指針指向返回int的無(wú)參函數(shù)
下面是錯(cuò)誤用法:
int *parr2[3](); // 錯(cuò)誤:錯(cuò)誤語(yǔ)法 int (*)() parr3[3]; // 錯(cuò)誤:錯(cuò)誤語(yǔ)法
解析parr1:
parr1先與[]結(jié)合,說(shuō)明它是一個(gè)數(shù)組- 數(shù)組的內(nèi)容是
int (*)()類(lèi)型的函數(shù)指針
函數(shù)指針數(shù)組常用于實(shí)現(xiàn)狀態(tài)機(jī)或回調(diào)函數(shù)機(jī)制,是C語(yǔ)言中一種強(qiáng)大的編程技術(shù)。
到此這篇關(guān)于深入解析C++中函數(shù)指針及其數(shù)組、typedef關(guān)鍵字用法舉例的文章就介紹到這了,更多相關(guān)C++函數(shù)指針 typedef關(guān)鍵字內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
嵌入式C語(yǔ)言二級(jí)指針在鏈表中的應(yīng)用
這篇文章主要為大家介紹了嵌入式C語(yǔ)言二級(jí)指針在鏈表中的應(yīng)用,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-04-04
C語(yǔ)言算法練習(xí)之?dāng)?shù)組求素?cái)?shù)
這篇文章主要為大家介紹了C語(yǔ)言算法練習(xí)中數(shù)組求素?cái)?shù)的實(shí)現(xiàn)方法,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C語(yǔ)言有一定幫助,需要的可以參考一下2022-09-09
C++20管道運(yùn)算符的實(shí)現(xiàn)示例
本文簡(jiǎn)要介紹C++20管道運(yùn)算符的使用與實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2025-06-06
Linux下C語(yǔ)言的fork()子進(jìn)程函數(shù)用法及相關(guān)問(wèn)題解析
fork()函數(shù)在Linux下可以用于產(chǎn)生一個(gè)子進(jìn)程,這里我們挑選了兩個(gè)fork相關(guān)的面試題,來(lái)看一下Linux下C語(yǔ)言的fork()子進(jìn)程函數(shù)用法及相關(guān)問(wèn)題解析2016-06-06
C++控制權(quán)限關(guān)鍵字protected
這篇文章主要介紹了C++控制權(quán)限關(guān)鍵字protected,protected和private類(lèi)似,而對(duì)于派生類(lèi)來(lái)說(shuō),protected與public類(lèi)似,下面來(lái)一起倆姐更多詳細(xì)內(nèi)容吧,需要的小伙伴可以參考一下2022-01-01
C++中volatile關(guān)鍵字的使用詳解以及常見(jiàn)的誤解
volatile 關(guān)鍵字是一種類(lèi)型修飾符,用它聲明的類(lèi)型變量表示可以被某些編譯器未知的因素更改,比如:操作系統(tǒng),硬件或者其他線程等2020-01-01
tc編譯的dos程序和vc編譯的win32控制臺(tái)程序的異同
tc編譯的dos程序和vc編譯的win32控制臺(tái)程序的異同...2007-08-08
C++編寫(xiě)DLL動(dòng)態(tài)鏈接庫(kù)的步驟與實(shí)現(xiàn)方法
這篇文章主要介紹了C++編寫(xiě)DLL動(dòng)態(tài)鏈接庫(kù)的步驟與實(shí)現(xiàn)方法,結(jié)合實(shí)例形式分析了C++導(dǎo)出類(lèi)文件及生成與調(diào)用DLL動(dòng)態(tài)連接庫(kù)的相關(guān)操作技巧,需要的朋友可以參考下2016-08-08

