網站首頁 編程語言 正文
一、函數類型
C 語言中的函數有自己特定的類型
函數的類型由返回值,參數類型和參數個數共同決定,如 int add(int i, int j)的類型為 int(int, int)
C 語言中通過 typedef 為函數類型重命名
typedef type name(parameter list)
如
typedef int f(int, int);
typedef void p(int);
二、函數指針
函數指針用于指向一個函數
函數名是執行函數體的入口地址
可通過函數類型定義函數指針:FuncType* pointer;
也可以直接定義: type (*pointer)(parameter list);
- pointer 為函數指針變量名
- type為所指函數的返回值類型
- parameter list 為所指函數的參數類型列表
下面看一個函數指針使用的代碼:
#include <stdio.h>
typedef int(FUNC)(int);
int test(int i)
{
return i * i;
}
void f()
{
printf("Call f()...\n");
}
int main()
{
FUNC* pt = test;
void(*pf)() = &f;
printf("pf = %p\n", pf);
printf("f = %p\n", f);
printf("&f = %p\n", &f);
pf();
(*pf)();
printf("Function pointer call: %d\n", pt(2));
return 0;
}
輸出結果如下:
注意:
1.FUNC* pt = test; 是合法的,test 這個函數名代表的是函數的入口地址,
2.對于函數名來說,取不取地址沒有區別,例如上面代碼中的 FUNC* pt = test; 也可以寫成FUNC* pt = &test;
3.(*pf)(); 相當于 f();
如果我們把void(*pf)() = &f; 改成void(*pf)() = 0x8048400; 直接利用函數指針跳轉到 0x8048400 這個地址來執行,結果照樣也能正常輸出:
面試小問題:如何使用 C 語言直接跳轉到某個固定的地址開始執行?
答案:通過函數指針
三、回調函數
回調函數是利用函數指針實現的一種調用機制
回調機制原理
- 調用者不知道具體事件發生時需要調用的具體函數
- 被調函數不知道何時被調用,只知道需要完成的任務
- 當具體事件發生時,調用者通過函數指針調用具體函數
回調機制中的調用者和被調函數互不依賴
下面看一個回調函數的使用示例:
#include <stdio.h>
typedef int(*Weapon)(int);
void fight(Weapon wp, int arg)
{
int result = 0;
printf("Fight boss!\n");
result = wp(arg);
printf("Boss loss: %d\n", result);
}
int knife(int n)
{
int ret = 0;
int i = 0;
for(i=0; i<n; i++)
{
printf("Knife attack: %d\n", 1);
ret++;
}
return ret;
}
int sword(int n)
{
int ret = 0;
int i = 0;
for(i=0; i<n; i++)
{
printf("Sword attack: %d\n", 5);
ret += 5;
}
return ret;
}
int gun(int n)
{
int ret = 0;
int i = 0;
for(i=0; i<n; i++)
{
printf("Gun attack: %d\n", 10);
ret += 10;
}
return ret;
}
int main()
{
fight(knife, 3);
fight(sword, 4);
fight(gun, 5);
return 0;
}
輸出結果如下:
四、小結
- C 語言中的函數都有特定的類型
- 可以使用函數類型定義函數指針
- 函數指針是實現回調機制的關鍵技術
- 通過函數指針可以在 C 程序中實現固定地址跳轉
原文鏈接:https://blog.csdn.net/weixin_43129713/article/details/123956023
相關推薦
- 2021-12-09 C語言求兩個正整數的最大公約數示例代碼_C 語言
- 2022-06-16 Kotlin對象比較注意點示例詳解_Android
- 2022-07-01 詳解go?mod?使用方法_Golang
- 2022-03-31 C語言類的雙向鏈表詳解_C 語言
- 2023-03-30 Regex正則表達式判斷密碼強度_正則表達式
- 2023-04-06 C++中的多態問題—理解虛函數表及多態實現原理_C 語言
- 2022-10-02 react中的useImperativeHandle()和forwardRef()用法_React
- 2022-07-21 數據庫之函數的使用
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支