深入解析C++中函數(shù)指針及其數(shù)組、typedef關(guān)鍵字用法舉例
一、函數(shù)指針變量的創(chuàng)建
1、什么是函數(shù)指針變量?
類比整型指針和數(shù)組指針的概念,我們可以得出:函數(shù)指針變量是用來存放函數(shù)地址的變量,通過這個地址我們可以調(diào)用相應(yīng)的函數(shù)。
2、函數(shù)是否有地址?
通過以下測試代碼可以驗證:
#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ù)名的方式獲取函數(shù)地址。(重點?。。。?/span>
3、創(chuàng)建函數(shù)指針變量
函數(shù)指針變量的聲明語法與數(shù)組指針類似:
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ù)指針類型解析
以int (*pf3)(int x, int y)為例:int (*) (int x, int y) 為pf3函數(shù)指針變量的類型

二、函數(shù)指針變量的使用
通過函數(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 (*)():這是一個函數(shù)指針類型,表示"指向一個沒有參數(shù)且返回void的函數(shù)的指針"。(void (*)())0:將整數(shù)值0強制轉(zhuǎn)換為上述函數(shù)指針類型。這表示"把地址0當(dāng)作一個函數(shù)的地址"。*(void (*)())0:解引用這個函數(shù)指針,得到位于地址0處的函數(shù)。(*(void (*)())0)():最后調(diào)用這個函數(shù)(通過函數(shù)指針調(diào)用)。
實際意義:這段代碼嘗試調(diào)用內(nèi)存地址0處的函數(shù)。在嵌入式系統(tǒng)中,這可能是調(diào)用復(fù)位向量或啟動代碼的方式。但在大多數(shù)現(xiàn)代操作系統(tǒng)中,這會引發(fā)段錯誤(segmentation fault),因為地址0通常是被保護的區(qū)域。
2、解釋void (*signal(int, void(*)(int)))(int);
這是一個函數(shù)聲明,聲明了名為signal的函數(shù)。讓我們分解它:
- 最內(nèi)層:
void(*)(int):這是一個函數(shù)指針類型,表示"指向一個接受int參數(shù)且返回void的函數(shù)的指針"。 signal(int, void(*)(int)):signal是一個函數(shù),它接受兩個參數(shù):一個int、一個上述類型的函數(shù)指針- 整個聲明:
void (*signal(int, void(*)(int)))(int):表示signal函數(shù)返回一個函數(shù)指針,這個指針指向"接受int參數(shù)且返回void的函數(shù)"。
更易讀的寫法(使用typedef,下面會講解):
typedef void (*sighandler_t)(int); // 定義函數(shù)指針類型 sighandler_t signal(int signum, sighandler_t handler);
實際意義:這是Unix/Linux系統(tǒng)中用于設(shè)置信號處理器的標(biāo)準(zhǔn)函數(shù)聲明。它:
- 接受一個信號編號(int)和一個處理該信號的函數(shù)指針
- 返回之前為該信號設(shè)置的處理函數(shù)指針
四、typedef關(guān)鍵字
typedef用于類型重命名,可以簡化復(fù)雜類型的聲明。
1、基本用法
typedef unsigned int uint; // 將unsigned int重命名為uint typedef int* ptr_t; // 將int*重命名為ptr_t
2、對于數(shù)組指針和函數(shù)指針的重命名
新的類型名必須在*的右邊:
typedef int(*parr_t)[5]; // 將數(shù)組指針類型int(*)[5]重命名為parr_t typedef void(*pfun_t)(int); // 將函數(shù)指針類型void(*)(int)重命名為pfun_t
3、使用typedef簡化代碼void (*signal(int, void(*)(int)))(int);
typedef void(*pfun_t)(int); pfun_t signal(int, pfun_t);
五、函數(shù)指針數(shù)組
數(shù)組是存放相同類型數(shù)據(jù)的存儲空間。我們已經(jīng)學(xué)過指針數(shù)組:
int *arr[10]; // 數(shù)組的每個元素是int*
如果要存儲函數(shù)地址,就需要使用函數(shù)指針數(shù)組。函數(shù)指針數(shù)組的定義方式:
int (*parr1[3])(); // 正確:包含3個函數(shù)指針的數(shù)組,每個指針指向返回int的無參函數(shù)
下面是錯誤用法:
int *parr2[3](); // 錯誤:錯誤語法 int (*)() parr3[3]; // 錯誤:錯誤語法
解析parr1:
parr1先與[]結(jié)合,說明它是一個數(shù)組- 數(shù)組的內(nèi)容是
int (*)()類型的函數(shù)指針
函數(shù)指針數(shù)組常用于實現(xiàn)狀態(tài)機或回調(diào)函數(shù)機制,是C語言中一種強大的編程技術(shù)。
到此這篇關(guān)于深入解析C++中函數(shù)指針及其數(shù)組、typedef關(guān)鍵字用法舉例的文章就介紹到這了,更多相關(guān)C++函數(shù)指針 typedef關(guān)鍵字內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于CLion配置visual?studio(msvc)和JOM多核編譯的問題
這篇文章主要介紹了CLion配置visual?studio(msvc)和JOM多核編譯,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-07-07
C語言詳細(xì)分析講解關(guān)鍵字const與volatile的用法
在C語言中,我們經(jīng)常會見到const和volatile這兩個關(guān)鍵字,那么我們今天就來介紹下這兩個關(guān)鍵字,提起?const?關(guān)鍵字,我們可能首先想到的是經(jīng)過它修飾的變量便是常量了。其實我們這種想法是錯誤的,其實?const?修飾的變量是只讀的,其本質(zhì)還是變量2022-04-04
C++ boost::asio編程-域名解析詳細(xì)介紹
這篇文章主要介紹了C++ boost::asio編程-域名解析詳細(xì)介紹的相關(guān)資料,這里附有實例代碼,幫助大家學(xué)習(xí)理解這部分知識,需要的朋友可以參考下2016-11-11

