国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

我們一起聊聊指針與函數

開發 前端
日常開發中,我還真沒找到指針函數的“優點”,讓我覺得某個功能必須用指針函數實現,或用指針函數實現后代碼更整潔,提高代碼可讀性。

指針函數

指針函數,從名字上看它本質上是一個函數。指針函數:返回值類型是指針的函數。函數聲明如下:

int *plusfunction(int a,int b);

當然也可以寫成如下格式:

int* plusfunction(int a,int b);

讓指針標志 * 與int緊貼在一起,而與函數名f間隔開,這樣看起來就明了些了,plusfunction是函數名,返回值類型是一個int類型的指針。

指針函數就是一個普通的函數,普通到僅僅是因為它的函數返回值是指針而已。

#include <stdio.h>
#include <stdlib.h>
int* plusfunction(int a,int b);
int main()
{
int *p = NULL;
p = plusfunction(1,2);
printf("*p is %d\n",*p);
free(p);
return(0);
}

int* plusfunction(int a,int b)
{
int *p = (int *) malloc( sizeof(int) );
*p = a + b;
return(p);
}

這是一個簡單的指針函數的例子,運行結果如下,本文代碼在VScode平臺運行,使用方法《使用VScode調試C語言》。

不過我有個疑問,使用指針函數,和函數入參是指針有什么好處呢???

#include <stdio.h>
#include <stdlib.h>
void plusfunction(int a,int b,int *p);
int main()
{
int *p = NULL;
p = (int *) malloc(sizeof(int) );
plusfunction(1,2,p);
printf("*p is %d\n",*p);
free(p);
return(0);
}

void plusfunction(int a,int b,int *p)
{
*p = a + b;
}

這樣執行也是沒問題的啊,當然我也發現了指針函數的好處,就是可以把函數作為另一個函數的入參。

testfunction(plusfunction(1,2));

在這點上用第二種方法,將指針作為函數入參是不行的。

還有,將指針作為函數入參前需要向指針申請內存,而指針函數卻不用。

除去這兩點,日常開發中,我還真沒找到指針函數的“優點”,讓我覺得某個功能必須用指針函數實現,或用指針函數實現后代碼更整潔,提高代碼可讀性。

函數指針

函數指針,本質上他是一個指針,并不是一個函數。在C語言中有些概念是一脈相承的,之前的推文《指針與數組》,數組指針和指針數組的概念更有效幫你理解函數指針和指針函數。函數指針說的就是一個指針,但這個指針指向的函數,不是普通的基本數據類型或者類對象。函數指針定義如下:

int (*f)(int a,int b);//聲明函數指針

和指針函數的定義對比可以看到,函數指針與指針函數的最大區別是函數指針的函數名是一個指針,即函數名前面有一個指針類型的標志型號“*”。注意指針函數與函數指針表示方法的不同,千萬不要混淆。最簡單的辨別方式就是看函數名前面的指針*號有沒有被括號()包含,如果被包含就是函數指針,反之則是指針函數。當然,函數指針的返回值也可以是指針。簡單的函數調用示例:

#include <stdio.h>
void MyFun(int a);
int main()
{
MyFun(10);
return(0);
}
void MyFun(int a)
{
printf("a is %d\n",a);
}

這是一個再簡單不過的函數調用了,其實他還可以寫作下面格式:

#include <stdio.h>
void MyFun(int a);
int main()
{
(*MyFun)(10);
return(0);
}
void MyFun(int a)
{
printf("a is %d\n",a);
}

這個代碼是正常運行的,也就是說(*MyFun)(10);和MyFun(10);是一樣的,在這里強烈建議沒有看過《指針與數組》的同學,先看一下。在教材和資料中,都會講到數組名就是指向數組第一個數據的常量指針。從上面例子看到,函數名貌似也是“常量指針”。數組中,可以將數組名賦給一個指針,然后通過指針訪問數組中的內容,那么我們就可以定義一個函數指針,將函數名賦給函數指針,通過這個函數指針調用函數。

#include <stdio.h>
void MyFun(int a);/* 這個聲明也可寫成:void MyFun( int )*/
void (*FunP)(int);/*也可聲明成void(*FunP)(int x),但習慣上一般不這樣。 */
int main()
{
FunP = MyFun;
*FunP(10);
return(0);
}
void MyFun(int a)
{
printf("a is %d\n",a);
}

在第7行在函數指針前加*相當取指針的值,在這里理解為將MyFun函數取出。那么再進一步:

#include <stdio.h>
void MyFun(int a); /* 這個聲明也可寫成:void MyFun( int )*/
void (*FunP)(int); /*也可聲明成void(*FunP)(int x),但習慣上一般不這樣。 */
int main()
{
FunP = MyFun;
FunP(10);
return (0);
}
void MyFun(int a)
{
printf("a is %d\n", a);
}

是的,將FunP前面的*號拿掉也是可以運行的,上面的示例代碼就是函數指針在C語言中的最常見形態。之前的例子只是為了讓你更能理解函數指針,實際開發中只需要用函數指針的最終,最常見的形態即可。

不然代碼中出現之前的形式,其他程序員并不是很熟悉,就成了“騷操作”,雖然不影響運行,但是降低代碼的可閱讀性。

typedef的引入

C語言中typedef關鍵字作用:復雜的聲明定義簡單的別名,很明顯我們上面講述的函數指針就是一個比較復雜的類型,可以使用typedef關鍵字將函數指針的定義簡單化。

#include <stdio.h>
void MyFun(int a); /* 這個聲明也可寫成:void MyFun( int )*/
typedef void (*FunType)(int); /*這樣只是定義一個函數指針類型 */
FunType FunP; /*然后用FunType類型來聲明全局FunP變量*/
int main()
{
FunP = MyFun;
FunP(10);
return (0);
}
void MyFun(int a)
{
printf("a is %d\n", a);
}

強烈建議使用typedef和函數指針組合的方式,這是最常見的方式,大家都能看懂的常規操作。在C語言的教程中typedef用于取別名,形式下:

typedef 舊名字 新名字;

確實也是這樣,但遇到給函數指針類型、數組類型等定義別名的時候就要特別區分了。如:


typedef char ARRAY20[20];
ARRAY20 a1,a2; /* 等價于char a1[20],a2[20]; */

typedef void (*FunType)(int); /*這樣只是定義一個函數指針類型 */
FunType FunP; /*然后用FunType類型來聲明全局FunP變量*/

別問我為什么,因為我也不知道。

當然,并不是說用到了函數指針就要用typedef定義一下,一般在結構體中使用函數指針就不會使用typedef,如下:

typedef struct
{
uint8_t data;
void (*FunP)(int);
}Mode_Typedef;

以上均為個人建議,沒有優劣,大家根據自己的習慣做即可。

函數指針作為入參

既然函數指針變量是一個變量,當然也可以作為某個函數的參數來使用的。所以,你還應知道函數指針是如何作為某個函數的參數來傳遞使用的。示例代碼如下:

#include <stdio.h>
void MyFun1(int x);
void MyFun2(int x);
void MyFun3(int x);
typedef void (*FunType)(int); /* ②. 定義一個函數指針類型FunType,與①函數類型一致 */
void CallMyFun(FunType fp, int x);
int main(int argc, char *argv[])
{
CallMyFun(MyFun1, 10); /* ⑤. 通過CallMyFun函數分別調用三個不同的函數 */
CallMyFun(MyFun2, 20);
CallMyFun(MyFun3, 30);
}
void CallMyFun(FunType fp, int x) /* ③. 參數fp的類型是FunType。*/
{
fp(x); /* ④. 通過fp的指針執行傳遞進來的函數,注意fp所指的函數是有一個參數的。 */
}
void MyFun1(int x) /* ①. 這是個有一個參數的函數,以下兩個函數也相同。 */
{
printf("MyFun1:%d\n", x);
}
void MyFun2(int x)
{
printf("MyFun2:%d\n", x);
}
void MyFun3(int x)
{
printf("MyFun3:%d\n", x);
}

運行結果如下:

可以看到,CallMyFun函數的參數是一個指針,當這個函數指針有參數時,需要通過另外增加一個參數來保存回調函數的參數值,同理也可以使用多個參數的函數指針。

單片機IAP

在單片機OTA時常用到函數指針,代碼如下:

typedef void (*IapFun)(void);//定義一個函數指針
IapFun Jump_To_Application;//定義函數指針對象
if (((*(__IO uint32_t*)appxaddr) & 0x2FFE0000 ) == 0x20000000)//檢查地址是否有效
{
Jump_To_Application = (iapfun) * (__IO uint32_t *)(appxaddr + 4);//用戶代碼區第二個字為程序開始地址(復位地址)
MSR_MSP(*(__IO uint32_t *)appxaddr);//初始化APP堆棧指針(用戶代碼區的第一個字用于存放棧頂地址)
Jump_To_Application();//跳轉app
}

這里直接將地址強制轉換成函數指針,然后執行這個函數。appxaddr地址就是新固件存儲的起始地址,appxaddr+4的位置就是新固建中的Reset_Handler函數,相當于執行了新固件中的Reset_Handler。

責任編輯:武曉燕 來源: 知曉編程
相關推薦

2023-08-04 08:20:56

DockerfileDocker工具

2023-08-10 08:28:46

網絡編程通信

2022-05-24 08:21:16

數據安全API

2023-06-30 08:18:51

敏捷開發模式

2023-09-10 21:42:31

2024-02-26 00:00:00

架構老化重構

2024-02-20 21:34:16

循環GolangGo

2021-08-27 07:06:10

IOJava抽象

2022-09-07 07:27:36

函數元素

2023-12-06 08:26:19

Service數據庫

2024-01-29 09:01:20

React列表模式

2023-07-04 08:06:40

數據庫容器公有云

2024-07-26 09:47:28

2022-02-23 08:41:58

NATIPv4IPv6

2024-11-28 09:57:50

C#事件發布器

2022-09-22 08:06:29

計算機平板微信

2023-03-26 23:47:32

Go內存模型

2021-08-12 07:49:24

mysql

2022-10-08 00:00:05

SQL機制結構

2023-07-24 09:41:08

自動駕駛技術交通
點贊
收藏

51CTO技術棧公眾號

mm131国产精品| 亚洲男同gay网站| 999国产精品| 精品不卡在线视频| 麻豆免费网站| 日本aⅴ亚洲精品中文乱码| 青青草原成人在线视频| 成人av三级| 欧美亚洲国产一区在线观看网站| 日本久久久久久久久久久久| 日本中文字幕不卡| 91精品免费久久久久久久久| 四虎地址8848精品| 欧美va在线播放| 最新地址在线观看| 久久99久久久久久久久久久| 亚洲一区二区中文| 亚洲欧美tv| 久久精品国产欧美亚洲人人爽| 国产乱色在线观看| 亚洲午夜在线电影| 国产免费又粗又猛又爽| 国产一本一道久久香蕉| 欧美第一黄网| 欧美日韩蜜桃| 91久久精品久久国产性色也91| 99精品国产一区二区三区2021| 日韩不卡中文字幕| 国产成人无吗| 在线国产电影不卡| 黄页网站免费在线观看| 国产亚洲一区二区在线观看| 日本一区二区三区四区五区六区| 亚洲资源av| 国产一区喷水| 亚洲高清av| 高清不卡日本v二区在线| 91精品国产91久久综合| 国产精品一区二区性色av| 欧美电影完整版在线观看| 中文日韩在线观看| 少妇精品视频一区二区免费看| 日韩毛片在线看| 韩国精品一区| 一区二区中文字幕| 欧美xxxx网站| 美日韩精品视频免费看| 欧美特黄不卡| 91av国产在线| 欧美激情15p| 国产精品小说在线| 欧美影视一区| 国产精品久久久久久久久久久久冷 | 一区二区三区视频观看| 欧美性片在线观看| www国产精品视频| 日韩第一区第二区| 国产69久久精品成人看| 欧美3p在线观看| 久久av免费观看| 国产乱对白刺激视频不卡| 欧美精品99久久| 1区2区3区欧美| 亚洲精品男人| 日韩三级视频在线看| 在线手机中文字幕| 久久成人av网站| 国产探花一区在线观看| 亚洲精品免费在线视频| 久色成人在线| 国产一区二区三区乱码| 91麻豆国产福利在线观看| 91破解版在线看| 欧美精品第1页| 蜜臀国产一区| 国产97在线视频| 国产亚洲综合精品| 给我免费播放片在线观看| 国产精品剧情在线亚洲| 六十路在线观看| 精品亚洲一区二区三区| a级日韩大片| 九九九九九精品| 久久先锋资源网| 欧美3p视频在线观看| 日韩av在线免费观看一区| 欧美日韩直播| 欧美一级日本a级v片| 国产三级久久久| 97视频在线观看网站| 久久精品国产久精国产思思| 欧美人与禽猛交乱配视频| 少妇无码av无码专区在线观看| 香蕉av福利精品导航| 亚洲天堂一区二区| 国产精品中文字幕在线| 国产乱对白刺激视频不卡| 久草在线在线| 色av吧综合网| 黑丝一区二区三区| 国产天堂在线播放| 欧美一区二区久久久| 全国精品免费看| 国产奶头好大揉着好爽视频| 亚洲国产aⅴ成人精品无吗| 欧美magnet| 粉嫩av四季av绯色av第一区| 久久久午夜电影| av在线麻豆| 国产精品视频久| 99精品欧美一区二区蜜桃免费 | 精品国产乱码久久久| 茄子视频成人在线观看| 中文字幕在线免费不卡| av女在线播放| 91精品婷婷国产综合久久蝌蚪| 91老师片黄在线观看| 麻豆av在线导航| 日本精品久久久久久久| 国产99一区视频免费| 蜜桃视频在线观看www社区| 日本午夜人人精品| av亚洲精华国产精华精| 综合图区亚洲| 91亚洲精品视频| 国产精品美女久久久久久2018| 依依综合在线| 奇米精品在线| 欧美日韩一区二区三区| 色哟哟精品丝袜一区二区| 人人干视频在线| 精品久久久久久最新网址| 在线精品小视频| 女人被爽到呻吟gif动态图下载| 搡老女人一区二区三区视频tv| 奇米在线7777在线精品| 高清美女视频一区| 国产精品永久免费视频| 成人欧美一区二区三区白人| 国产精品99精品一区二区三区∴| 日韩精品电影网站| 欧美日韩国产美| 亚洲视频一区| 国产片在线观看| 99国精产品一二二线| 欧美色播在线播放| 五月激情综合| 在线视频2区| 欧美伊人久久大香线蕉综合69 | 欧美高清在线一区| 国产91精品入口| 久久久久久穴| 国产一区二区三区四区五区美女| 日韩激情视频网站| 狠狠干狠狠久久| 欧美一级二级在线观看| 亚洲欧美国产精品久久久久久久| 中文字幕亚洲二区| 天天操天天爱天天爽| 在线观看h网| 日韩欧美一级| 国产乱淫av一区二区三区| 日韩欧美你懂的| 精品处破学生在线二十三| 99久久精品久久久久久ai换脸| 国产精品自拍片| 高h视频在线播放| 国产精品普通话对白| 国产黄色小视频在线| 污污污污污污www网站免费| 久久久久久久久久久免费| 天天色天天操综合| 免费人成在线不卡| 色成人综合网| 中文在线三区| 一区二区不卡在线视频 午夜欧美不卡'| 久久精品成人动漫| 欧美日韩国产精品专区 | 97免费中文视频在线观看| 欧美日韩在线另类| 麻豆一区二区99久久久久| 久久综合另类图片小说| 日本在线视频观看| 精品久久久久久久无码| 国产精品免费一区二区三区观看 | 久久综合九色综合97婷婷| 欧美肉体xxxx裸体137大胆| 人人澡人人添人人爽一区二区| 亚洲中文字幕无码中文字| 99热99热| 久久免费成人精品视频| 日韩欧美成人激情| 欧美在线激情视频| 欧美精品在线观看播放| 久久精品综合网| 青青草国产成人av片免费| 91欧美在线| 成人激情自拍| 在线观看特色大片免费视频| 欧美美女色图|