C語言深入淺出分析函數(shù)指針
我們先看一個(gè)代碼:
#include<stdio.h> void test() { printf("haha\n"); } int main() { printf("%p\n", test); printf("%p\n", &test); return 0; }
輸出的是兩個(gè)地址,函數(shù)名就是函數(shù)的地址
將函數(shù)的地址存起來:
#include<stdio.h> void test() { printf("haha\n"); } int main() { //函數(shù)指針 int (*pf)(const char*) = test; (*pf)("abc"); pf("abc"); test("abc"); return 0; }
函數(shù)指針也是一種指針,是指向函數(shù)的指針
int (*pf)(const char*) = test
pf先和*結(jié)合,是指針,指向test函數(shù),無參數(shù),返回值類型為void
《C陷阱和缺陷》中的一段代碼:
( *(void (*)())0 )();
void(*)()是函數(shù)指針類型
( void (*)() )0 是強(qiáng)制類型轉(zhuǎn)換,結(jié)果是函數(shù)的地址,0地址中存放一個(gè)函數(shù),無參數(shù),無返回值
以上代碼總體是一次函數(shù)調(diào)用,調(diào)用的是0作為地址處的函數(shù),首先把0強(qiáng)制轉(zhuǎn)換為無參,返回類型是void的函數(shù)的地址,其次是調(diào)用0地址處的這個(gè)函數(shù)
再觀察這段代碼:
void (*signal(int , void(*)(int)))(int);
代碼可以化簡:
把void(*)(int)重命名為pfun_t
typedef void(*pfun_t)(int); pfun_t signal(int, pfun_t);
signal 與后面的括號(hào)結(jié)合,是函數(shù)名
( int , void(*)(int) ) 是兩個(gè)參數(shù)類型
以上代碼是一次函數(shù)聲明 ,signal函數(shù)的第一個(gè)參數(shù)的類型是int,第二個(gè)參數(shù)類型是函數(shù)指針,該指針指向的是一個(gè)參數(shù)類型為int,返回值為空的函數(shù),signal函數(shù)的返回類型也是一個(gè)指針函數(shù),該函數(shù)指針也指向的是一個(gè)參數(shù)類型為int,返回值為空的函數(shù)
使用函數(shù)指針簡化代碼:
當(dāng)功能近似的函數(shù)中有較多相同的代碼時(shí),可以用函數(shù)指針來簡化代碼
void calc( int(*pf) (int, int) )
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> void menu() { printf("*****************\n"); printf("***1.sum 2.sub***\n"); printf("***3.mul 4.div***\n"); printf("*****0.退出*****\n"); printf("*********\n"); } 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; } //計(jì)算 void calc(int(*pf)(int, int)) { int x = 0; int y = 0; int ret = 0; printf("輸入兩個(gè)操作數(shù):"); scanf("%d%d", &x, &y); ret = pf(x, y); printf("%d\n", ret); } int main() { int input = 0; do { menu(); printf("請(qǐng)選擇"); scanf("%d", &input); switch(input) { case 1: calc(add); break; case 2: calc(sub); break; case 3: calc(mul); break; case 4: calc(div); break; case 0: printf("退出計(jì)算器!\n"); break; default: printf("選擇錯(cuò)誤!\n"); break; } } while (input); return 0; }
上述代碼使用了回調(diào)函數(shù),回調(diào)函數(shù)就是一個(gè)通過函數(shù)指針調(diào)用的函數(shù)。如果你把函數(shù)的指針(地址)作為參數(shù)傳遞給另一個(gè)函數(shù),當(dāng)這個(gè)指針被用來調(diào)用其所指向的函數(shù)時(shí),我們就說這是回調(diào)函數(shù)。回調(diào)函數(shù)不是由該函數(shù)的實(shí)現(xiàn)方直接調(diào)用,而是在特定的事件或條件發(fā)生時(shí)由另外的一方調(diào)用的,用于對(duì)該事件或條件進(jìn)行響應(yīng)。
到此這篇關(guān)于C語言深入淺出分析函數(shù)指針的文章就介紹到這了,更多相關(guān)C語言函數(shù)指針內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++使用boost::lexical_cast進(jìn)行數(shù)值轉(zhuǎn)換
這篇文章介紹了C++使用boost::lexical_cast進(jìn)行數(shù)值轉(zhuǎn)換的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06對(duì)比C語言中execv相關(guān)的執(zhí)行文件的三個(gè)函數(shù)
這篇文章主要介紹了對(duì)比C語言中execv相關(guān)的執(zhí)行文件的三個(gè)函數(shù),分別為execv()函數(shù)和execve()函數(shù)以及execvp()函數(shù),需要的朋友可以參考下2015-08-08