函數(shù)是C語言的核心概念。主調(diào)函數(shù)(caller)調(diào)用被調(diào)函數(shù)(callee)是一般的調(diào)用關(guān)系,如果被調(diào)函數(shù)(callee)參數(shù)包含函數(shù)指針,函數(shù)指針還可以形成多一層的調(diào)用關(guān)系,形成第三方函數(shù)的調(diào)用,專業(yè)術(shù)語稱為回調(diào)(callback),通過函數(shù)指針參數(shù)調(diào)用的第三方函數(shù)稱為回調(diào)函數(shù)。
回調(diào)可以讓被調(diào)函數(shù)(這里是指用函數(shù)指針做函數(shù)參數(shù)的函數(shù))的代碼更加泛化或抽象,能夠簡(jiǎn)單模擬其它編程語言的委托與反射語法。
1、簡(jiǎn)單模擬委托
//C語言簡(jiǎn)單模擬委托
//需要用的指針函數(shù)。通過用指針函數(shù)作為地址接收函數(shù)地址,以達(dá)到委托其他函數(shù)實(shí)現(xiàn)某方法的目的。
#include
typedefvoid(*fun)();//typedef把void(*)()類型重命名為fun
voidfunc(fun);//被調(diào)函數(shù)
voidfunc_1();//回調(diào)函數(shù)1
voidfunc_2();//回調(diào)函數(shù)2
intmain()//主函數(shù)用做主調(diào)函數(shù)
{
func(func_1);
funf=func_2;
f();
func(func_1);
func(func_2);
getchar();
return0;
}
voidfunc(funf)//funf為地址,fun*f為f指向的地址的量或者其他
{
printf("func
");
if(f!=NULL)
{
f();
}
}
voidfunc_1()
{
printf("func_1
");
}
voidfunc_2()
{
printf("func_2
");
}
/*
func
func_1
func_2
func
func_1
func
func_2
*/
2、簡(jiǎn)單模擬反射
(1)簡(jiǎn)單模擬反射
高級(jí)語言的反射機(jī)制,簡(jiǎn)單來說,就是可以通過字符串型獲取對(duì)應(yīng)的類或者函數(shù)。下面,用C來簡(jiǎn)單模擬反射:
#include
#include
typedefvoid(*callback)(void);
typedefstruct{
constchar*name;
callbackfn;
}callback_t;
voidf0();
voidf1();
callback_tcallbacks[]={
{"cmd0",f0},
{"cmd1",f1},
};
voidf0()//回調(diào)函數(shù)0
{
printf("cmd0");
}
voidf1()//回調(diào)函數(shù)1
{
printf("cmd1");
}
voiddo_callback(constchar*name)
{
size_ti;
for(i=0;isizeof(callbacks)/sizeof(callbacks[0]);i++){
if(!strcmp(callbacks[i].name,name)){
callbacks[i].fn();
}
}
}
intmain()
{
do_callback("cmd1");
getchar();
return0;
}
(2)利用自定義段
gcc支持通過使用 __ attribute __ ((section())),將函數(shù)、變量放到指定的數(shù)據(jù)段中。也就是說,可以讓編譯器幫我們完成上例中向數(shù)組添加成員的動(dòng)作。
借助此機(jī)制,回調(diào)函數(shù)可以在任意文件聲明,不需要修改其他文件。自定義段的起始和結(jié)束地址,可以通過變量 __ start_SECTIONNAME 和 __ stop_SECTIONNAME得到例如通過 __ attribute __ ((section("ss"))定義自定義段,其開始地址為 & __ start_ss,結(jié)束地址為 & __stop_ss。
//https://www.bejson.com/runcode/c920/
#include
#defineSEC__attribute__((__section__("ss"),aligned(sizeof(void*))))
voidfunc_1(inta,intb)
{
printf("%s%d%d
",__func__,__LINE__,a+b);
}
voidfunc_2(inta,intb)
{
printf("%s%d%d
",__func__,__LINE__,a*b);
}
//編譯器會(huì)自動(dòng)提供__start_ss,__stop_ss標(biāo)志段ss的起止地址
externsize_t__start_ss;
externsize_t__stop_ss;
typedefstruct{
void(*p)(int,int);
}node_t;
//結(jié)構(gòu)體變量a位于自定義段ss
SECnode_ta={
.p=func_1,
};
SECnode_tb={
.p=func_2,
};
intmain(intargc,char**argv)
{
inta=3,b=4;
node_t*p;
//遍歷段ss,執(zhí)行node_t結(jié)構(gòu)中的p指向的函數(shù)
for(p=(node_t*)&__start_ss;p(node_t*)&__stop_ss;p++){
p->p(a,b);
a+=1;b+=2;
}
}
/*
func_167
func_21024
*/
原文標(biāo)題:C語言使用回調(diào)函數(shù)模擬委托與反射
文章出處:【微信公眾號(hào):硬件攻城獅】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
-
參數(shù)
+關(guān)注
關(guān)注
11文章
1865瀏覽量
32771 -
C語言
+關(guān)注
關(guān)注
180文章
7628瀏覽量
139706 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4365瀏覽量
63855
原文標(biāo)題:C語言使用回調(diào)函數(shù)模擬委托與反射
文章出處:【微信號(hào):mcu168,微信公眾號(hào):硬件攻城獅】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
簡(jiǎn)單交通燈并簡(jiǎn)單模擬車輛運(yùn)行方向
單模光纖-你應(yīng)該選擇什么樣的?
藍(lán)牙單模和雙模的區(qū)別
DigiPCBA 庫遷移系列 - 簡(jiǎn)單模式
塔臺(tái)模擬機(jī)飛行進(jìn)程單模塊的設(shè)計(jì)與實(shí)現(xiàn)
LOG100的簡(jiǎn)單模式對(duì)數(shù)放大電路

SIMULINK簡(jiǎn)單模型的建立及模型特點(diǎn)
S7-200簡(jiǎn)單模擬量編程程序
簡(jiǎn)單模擬控制的單相VIENNA整流器研究

評(píng)論