大家好,我是雜燴君
。本次給大家分享幾個嵌入式C中的實用技巧。
1、動態綁定、回調函數
回調函數可以達到動態綁定的作用,在一定程度上可以降低層與層之間的耦合。關于回調函數,之前已經有寫過一篇:C語言、嵌入式重點知識:回調函數??赡芎芏喑鯇W的小伙伴可能還不理解回調函數,可以借助下圖來理解:
![5fba2c48-c126-11ec-bce3-dac502259ad0.jpg](https://file1.elecfans.com//web2/M00/95/46/wKgaomTm-S2AFTB3AABweHYKqgc615.jpg)
一般函數調用的順序都是上層函數(調用者)調用下層函數(被調用者)。而通過上圖我們可以看到下層模塊的函數2調用了上層模塊的函數3,這個調用過程與一般的調用過程相反,這個過程叫做回調,這里上層模塊的函數3就是回調函數?;卣{函數的表現形式是函數指針。
C庫stdlib.h中帶有一個排序函數:qsort函數。這個排序函數的原型為:
voidqsort(void*base,size_tnitems,size_tsize,int(*compar)(constvoid*,constvoid*));
參數:
- base-- 指向要排序的數組的第一個元素的指針。
- nitems-- 由 base 指向的數組中元素的個數。
- size-- 數組中每個元素的大小,以字節為單位。
- compar-- 用來比較兩個元素的函數,即函數指針(回調函數)。
intcompar(constvoid*p1,constvoid*p2);
如果compar返回值小于0(< 0),那么p1所指向元素會被排在p2所指向元素的左面;
如果compar返回值等于0(= 0),那么p1所指向元素與p2所指向元素的順序不確定;
如果compar返回值大于0(> 0),那么p1所指向元素會被排在p2所指向元素的右面。
例子:
![5fcfedf8-c126-11ec-bce3-dac502259ad0.jpg](https://file1.elecfans.com//web2/M00/95/46/wKgaomTm-S2ABf0_AAB4PwlS77M285.jpg)
#include
#include
intcompar_int(constvoid*p1,constvoid*p2)
{
return(*((int*)p1)-*((int*)p2));
}
voidtest_qsort(void)
{
intarr[5]={8,5,10,1,100};
printf("排序前:");
for(inti=0;i5;i++)
{
printf("%d",arr[i]);
}
qsort((int*)arr,5,4,compar_int);
printf("
排序后:");
for(inti=0;i5;i++)
{
printf("%d",arr[i]);
}
}
intmain(void)
{
test_qsort();
return0;
}
編譯、運行結果:
![5fe79296-c126-11ec-bce3-dac502259ad0.jpg](https://file1.elecfans.com//web2/M00/95/46/wKgaomTm-S2AZ126AABf2tHZHq8253.jpg)
以上就是本次的分享,如有錯誤,歡迎指出,謝謝。這是第一彈,后續還會繼續分享更多實際開發中實用的編程小技巧及編程經驗。歡迎持續關注。本文只是盤點了一些實用小技巧,并不是說無論什么場景下都要這么用,還需具體問題具體分析。
2、使用宏給結構體初始化
如果頻繁使用一個結構體的話,使用使用宏來給結構體進行賦值是很方便的一種做法。
例子:
#include
#defineNEW_RECT(length,width){(length),(width)}
typedefstruct_Rect
{
intlength;
intwidth;
}Rect;
intmain(void)
{
Rectrect=NEW_RECT(10,5);
printf("rectlength=%d,width=%d
",rect.length,rect.width);
return0;
}
編譯、運行結果:
![5ffc9ba0-c126-11ec-bce3-dac502259ad0.jpg](https://file1.elecfans.com//web2/M00/95/46/wKgaomTm-S6AKKPJAABjaA29LMs910.jpg)
這種方法在RT-Thread的底層gpio驅動中也有見到:
![601a1b94-c126-11ec-bce3-dac502259ad0.jpg](https://file1.elecfans.com//web2/M00/95/46/wKgaomTm-S6AUm2-AADvAZjSi1A508.jpg)
3、結構體內置函數指針
我們常常構造一些結構體來存儲數據,然后在一些函數中使用這些結構體。下次不妨把數據與操作數據的函數綁在一起,更清晰明了。
相關文章:什么是不完全類型?
例子:
#include
#defineNEW_RECT(length,width){(calc_area),(length),(width)}
typedefstruct_Rect
{
int(*calc_area)(struct_Rect*pThis);
intlength;
intwidth;
}Rect;
intcalc_area(struct_Rect*pThis)
{
return(pThis->length*pThis->width);
}
intmain(void)
{
Rectrect=NEW_RECT(10,5);
printf("rectlength=%d,width=%d
",rect.length,rect.width);
printf("rectarea=%d
",rect.calc_area(&rect));
return0;
}
編譯、運行結果:
![602f9b68-c126-11ec-bce3-dac502259ad0.jpg](https://file1.elecfans.com//web2/M00/95/46/wKgaomTm-S6AWSa5AABlO5BdBVI004.jpg)
4、使用do{}while(0)封裝宏
#defineDBG_PRINTF(fmt,args...)
do
{
printf("<>" ,__FILE__,__LINE__,__FUNCTION__);
printf(fmt,##args);
}while(0)
具體說明可查閱往期文章:
5、void*
之前在C語言對象編程第一彈:封裝與抽象中有介紹過void*
。void*
其實我們平時都有接觸過,比如:
void*malloc(size_tsize);
void*memcpy(void*destin,void*source,unsignedn);
......
void *
常常用于函數地封裝比較多,當然也有用在其它地方,比如在結構體內定義void*
類型的私有指針方便擴展結構體。我們平時在封裝自己的函數時,也可以多考慮看看有沒有必要使用void*
使得函數地通用性更強一些。
end
審核編輯 :李倩
-
嵌入式
+關注
關注
5096文章
19199瀏覽量
308252 -
函數
+關注
關注
3文章
4350瀏覽量
63047
原文標題:分享幾個嵌入式 C 中的實用技巧
文章出處:【微信號:yikoulinux,微信公眾號:一口Linux】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
分享幾個嵌入式學習的小技巧
幾個硬件和嵌入式軟件的問題
嵌入式實時程序設計中C/C++代碼的優化
嵌入式C的主要特點以及嵌入式C與標準C異同沖區重用
嵌入式C++編程
![<b class='flag-5'>嵌入式</b><b class='flag-5'>C</b>++編程](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
嵌入式C語言知識總結
![<b class='flag-5'>嵌入式</b><b class='flag-5'>C</b>語言知識總結](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
嵌入式C語言的結構特點
![<b class='flag-5'>嵌入式</b><b class='flag-5'>C</b>語言的結構特點](https://file1.elecfans.com/web2/M00/B2/95/wKgZomVgW6iABkkQAAEAUboqAJY986.jpg)
評論