網站首頁 編程語言 正文
一、函數指針
1.概念
函數指針:首先它是一個指針,一個指向函數的指針,在內存空間中存放的是函數的地址;
請看示例:
int main(){
int a = 10;
int*pa = &a;
char ch = 'c';
char* pc = &ch;
int arr[10] = {0};
int (*parr)[10] = &arr;//取出數組的地址
return 0;
}
解析:parr是一個指向數組的指針,存放的是數組的地址;
所以:
- 數組指針 —存放數組地址的指針;
- &數組名 —得到的就是數組的地址;
那么我們可以不可以這么認為:
- 函數指針 —存放函數地址的指針;
- &函數名 —得到的就是一個函數的地址;
是這樣嗎?我們來測試一下,請看下面事例:
int Add(int x,int y)
{
return x+y;
}
int main()
{
printf("%p\n",&Add);//打印一下函數Add()的地址
printf("%p\n",Add);//數組名等于數組首元素地址,那函數名是等于函數地址嗎?
return 0;
}
請看結果:
哦!原來,函數名是等于函數地址的!
1.2函數指針的使用方法
函數指針的定義: 函數的返回值類型(*指針名)(函數的參數列表類型)
int Add(int x, int y)
{
return x+y;
}
int main()
{
int (*pf)(int, int) = &Add;//函數指針定義,返回值類型和參數類型與函數Add()相同
}
1.3練習鞏固
void test(char* str){}
int main (){
①(?)pt =&test;
return 0;
}
請問①語句應該怎么完善呢?
答案:void ( * pt)(char*) = &test;
怎么使用函數指針去調用函數呢?
還是上面的例子:
void Add(int x, int y){
return x+y;}
int main(){
int (*pf)(int,int)=&Add;
int ret=(*pf)(3,5);
解析:
int ret=(*pf)(3,5),此時就相當于通過函數名調用: int ret=Add(3,5);},我們又知道:函數名是等于&函數名的,所以int (*pf)(int,int)=&Add,可改成:int (*pf)(int,int)=Add;此時Add等價于pf,所以:int ret=(*pf)(3,5);語句可改成:int ret=pf(3,5);等價于int ret=Add(3,5),故我們知道了對于:int ret=(*pf)(3,5);語句來說,*是沒有意義的,有一個或多個或者沒有都不影響;
1.4小結一下
數組名 (arr) != &數組名(&arr)
函數名(Add) = &函數名(&Add)
二、閱讀兩段有趣的代碼
注:來源于《c陷阱和缺陷》;
1.( *(void( *)( ))0 )( )
解析:
調用0地址處的函數該函數無參數,返回值是void拆分:
這段代碼的含義是:
●void()() 表示函數指針類型
●( void()() )0 表示對0進行強制類型轉換,把0強制類型轉換成一個函數的地址;如(int)3.14
●* ( void()() )0 表示對0地址處的函數進行了解引用操作
●( ( void(*)() )0)() 則表示調用0地址處的函數
請看圖解:![]()
2.void (* signal(int,void( * )( int ) ) )(int)
解析:
1.signal和()先結合,說明signal是一個函數名
2.signal函數第一個參數的類型為int,第二個參數的類型為函數指針,該函數指針指向一個參數為int,返回值為void的函數;
3.signal 函數的返回類型也是一個函數指針,該函數指針,指向一個參數為int,返回值為void函數
4.請看圖解:![]()
綜上,signal是一個函數聲明;
附:函數指針的應用——函數回調
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define arrLen 10
void selectSort(int *p,int n,int (*pf)(int ,int )){
for(int i = 0;i<n-1;i++){
for(int j=i+1;j<n;j++){
if(pf(p[i],p[j])){
p[i] = p[i]^p[j];
p[j] = p[i]^p[j];
p[i] = p[i]^p[j];
}
}
}
}
//只需修改啊a>B 或a<b,不用修改 selectSort就可以實現降序升序排列
//這就是函數回調帶來的便利
//這也是函數指針一種應用
int callBack(int a,int b){
return a<b?1:0;
}
int main(void){
srand(time(NULL));
int arr[arrLen] ;
for(int i = 0;i<arrLen;i++){
arr[i] = rand()%100+1;
}
selectSort(arr,arrLen,callBack);
for(int i = 0;i<arrLen;i++){
printf("%5d",arr[i]);
}
return 0;
}
總結
原文鏈接:https://blog.csdn.net/m0_46569169/article/details/124318184
相關推薦
- 2023-02-09 React?Context原理深入理解源碼示例分析_React
- 2022-08-14 Oracle中dbms_output.put_line的用法實例_oracle
- 2022-04-15 玩數據必備Python庫之numpy使用詳解_python
- 2022-09-13 iOS封裝倒計時按鈕HLCountDownButton示例詳解_IOS
- 2023-02-10 WPF實現圓形進度條的示例代碼_C#教程
- 2024-02-01 webstorm中Line comment at first column,Block commen
- 2022-05-23 單點登錄之cas集成sonar的配置方法_相關技巧
- 2022-08-13 Flutter實現不同縮放動畫效果詳解_Android
- 最近更新
-
- 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同步修改后的遠程分支