大家好,我是雜燴君。本次給大家分享幾個嵌入式C中的實用技巧。
回調函數可以達到動態綁定的作用,在一定程度上可以降低層與層之間的耦合。關于回調函數,之前已經有寫過一篇:C語言、嵌入式重點知識:回調函數。可能很多初學的小伙伴可能還不理解回調函數,可以借助下圖來理解:

一般函數調用的順序都是上層函數(調用者)調用下層函數(被調用者)。而通過上圖我們可以看到下層模塊的函數2調用了上層模塊的函數3,這個調用過程與一般的調用過程相反,這個過程叫做回調,這里上層模塊的函數3就是回調函數。回調函數的表現形式是函數指針。
C庫stdlib.h中帶有一個排序函數:qsort函數。這個排序函數的原型為:
void?qsort(void?*base,?size_t?nitems,?size_t?size,?int?(*compar)(const?void?*,?const?void*));
參數:
int?compar(const?void?*p1,?const?void?*p2);
如果compar返回值小于0(< 0),那么p1所指向元素會被排在p2所指向元素的左面;
如果compar返回值等于0(= 0),那么p1所指向元素與p2所指向元素的順序不確定;
如果compar返回值大于0(> 0),那么p1所指向元素會被排在p2所指向元素的右面。

#include?
#include?
int?compar_int(const?void?*p1,?const?void?*p2)
{
?return?(*((int*)p1)?-?*((int*)p2));
}
void?test_qsort(void)
{
?int?arr[5]?=?{8,?5,?10,?1,?100};
?
?printf("排序前:");
?for?(int?i?=?0;?i?5;?i++)
?{
??printf("%d?",?arr[i]);
?}
?
?qsort((int*)arr,?5,?4,?compar_int);
?
?printf("\n排序后:");
?for?(int?i?=?0;?i?5;?i++)
?{
??printf("%d?",?arr[i]);
?}
}
int?main(void)
{
?test_qsort();
?return?0;
}
編譯、運行結果:

以上就是本次的分享,如有錯誤,歡迎指出,謝謝。這是第一彈,后續還會繼續分享更多實際開發中實用的編程小技巧及編程經驗。歡迎持續關注。本文只是盤點了一些實用小技巧,并不是說無論什么場景下都要這么用,還需具體問題具體分析。
如果頻繁使用一個結構體的話,使用使用宏來給結構體進行賦值是很方便的一種做法。
#include?
#define??NEW_RECT(length,?width)??{(length),?(width)}
typedef?struct?_Rect
{
?int?length;
?int?width;
}Rect;
int?main(void)
{
?Rect?rect?=?NEW_RECT(10,?5);
?printf("rect?length?=?%d,?width?=?%d\n",?rect.length,?rect.width);
?return?0;
}

這種方法在RT-Thread的底層gpio驅動中也有見到:

我們常常構造一些結構體來存儲數據,然后在一些函數中使用這些結構體。下次不妨把數據與操作數據的函數綁在一起,更清晰明了。
相關文章:什么是不完全類型?
#include?
#define??NEW_RECT(length,?width)??{(calc_area),?(length),?(width)}
typedef?struct?_Rect
{
?int?(*calc_area)(struct?_Rect?*pThis);
?int?length;
?int?width;
}Rect;
int?calc_area(struct?_Rect?*pThis)
{
?return?(pThis->length?*?pThis->width);
}
int?main(void)
{
?Rect?rect?=?NEW_RECT(10,?5);
?printf("rect?length?=?%d,?width?=?%d\n",?rect.length,?rect.width);
?printf("rect?area?=?%d\n",?rect.calc_area(&rect));
?return?0;
}

#define?DBG_PRINTF(fmt,?args...)??\
do\
{\
????printf("<>?" ,?__FILE__,?__LINE__,?__FUNCTION__);\
????printf(fmt,?##args);\
}while(0)
具體說明可查閱往期文章:
C語言、嵌入式中幾個非常實用的宏技巧
之前在C語言對象編程第一彈:封裝與抽象中有介紹過void*。void*其實我們平時都有接觸過,比如:
void?*malloc(size_t?size)?;
void?*memcpy(void?*destin,?void?*source,?unsigned?n);
......
void *常常用于函數地封裝比較多,當然也有用在其它地方,比如在結構體內定義void*類型的私有指針方便擴展結構體。我們平時在封裝自己的函數時,也可以多考慮看看有沒有必要使用void*使得函數地通用性更強一些。
如果本文對你有幫助,不妨轉發分享,謝謝~
推薦閱讀
01 |加入嵌入式交流群 |
02 |嵌入式資源獲取 |
03 |STM32中斷優先級詳解 |
04 |STM32下載程序新思路--使用串口下載程序 |

