網(wǎng)站首頁 編程語言 正文
我們先看一個(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("請選擇");
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)。
原文鏈接:https://blog.csdn.net/chenchenchencl/article/details/125645782
相關(guān)推薦
- 2022-04-04 scrapy框架中用ssh連接遠(yuǎn)程服務(wù)器的實(shí)現(xiàn)_python
- 2023-01-10 Oracle如何獲取數(shù)據(jù)庫系統(tǒng)的當(dāng)前時(shí)間_oracle
- 2022-03-27 Android自定義模擬時(shí)鐘控件_Android
- 2022-09-26 React 函數(shù)式組件怎樣進(jìn)行優(yōu)化
- 2023-03-20 Redis腦裂導(dǎo)致數(shù)據(jù)丟失的解決_Redis
- 2024-03-07 基于配置類方式管理Bean
- 2022-12-01 C/C++細(xì)數(shù)宏與函數(shù)有那些區(qū)別_C 語言
- 2022-06-02 Z-Order加速Hudi大規(guī)模數(shù)據(jù)集方案分析_服務(wù)器其它
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支