嵌入式
因?yàn)樽约哼@幾年來一直從事嵌入式系統(tǒng)底層驅(qū)動(dòng)開發(fā),操作系統(tǒng)uc/OS,文件系統(tǒng)維護(hù)以及平臺(tái)搭建工作,在這幾年的工作中學(xué)習(xí)到不少系統(tǒng)方面的經(jīng)驗(yàn),現(xiàn)寫下來一來是分享給大家,二來是作一個(gè)總結(jié),三來是望得到各位大蝦的批評(píng)指正?,F(xiàn)打算從如下幾個(gè)方面分類總結(jié)一下:
(一),預(yù)處理
(二),可移植性
(三),警惕潛在危險(xiǎn)
(四),對(duì)齊與大小端模式
(五),效能問題
(六),重入問題
好像很難得將一個(gè)方面的內(nèi)容一刀切的劃分到一個(gè)主題中,例如:宏定義既是屬于預(yù)處理內(nèi)容,又跟效能有關(guān)系,還涉及到潛在危險(xiǎn)... 所以,(一),(二),(三)...的劃分不一定規(guī)范(咱又不是寫書 ^_^),且會(huì)在不同的地方對(duì)某個(gè)問題進(jìn)行不同重點(diǎn)的總結(jié)。
============ 預(yù)處理 ================
1. 頭文件
一般來講很難保證在一個(gè)大型的項(xiàng)目軟件中,某個(gè)頭文件不被重復(fù)的引用,例如,在嵌入式系統(tǒng)中往往為了軟件的可移植性,都會(huì)有一個(gè)對(duì)所有數(shù)據(jù)類型的采用宏定義或者typedef定義的頭文件,我們假定為portable.h,其內(nèi)容如下:
#define INT8S char
#define INT8U unsigned char
#define INT16S short
#define INT16U unsigned short
#define INT32S int
#define INT32U unsigned int
類似于這種類型的頭文件肯定會(huì)被其他的頭文件多次引用,假定有component.h 和system.h兩個(gè)頭文件引用了portable.h,而在某個(gè).c文件中引用了component.h和system.h那么編譯器在進(jìn)行預(yù)處理的時(shí)候會(huì)對(duì)這個(gè).c文件中引用的所有頭文件進(jìn)行展開,這樣portable.h中的宏定義會(huì)被多次展開,編譯器發(fā)現(xiàn)有多次重復(fù)定義同一個(gè)宏定義的問題,那么編譯器會(huì)報(bào)錯(cuò)/報(bào)警告。
為了避免這樣的問題,我們對(duì)每個(gè)頭文件加入條件編譯。
#ifndef __portable_h__
#define __portable_h__
#define INT8S char
#define INT8U unsigned char
#define INT16S short
#define INT16U unsigned short
#define INT32S int
#define INT32U unsigned int
#endif
這樣當(dāng),portable.h頭文件在某個(gè)地方被展開后就會(huì)#define __portable_h__,那么在其他的地方有重復(fù)引用portable.h時(shí),#ifndef __portable_h__ 是不成立的,所以,就不會(huì)對(duì)portable.h的內(nèi)容重復(fù)展開了.
2. 條件預(yù)處理
#if ,#else, #endif應(yīng)該是大家經(jīng)常會(huì)用到的。
比如說,有兩段代碼在前期調(diào)試的時(shí)候會(huì)經(jīng)常切換使用不同的代碼,那么我們可能會(huì)寫成如下方式:
形式1:
#if 0
gTestCount = a + b;
…….
#else
gTestCount = (a<<1) + b;
……
#endif
這種方式是最簡(jiǎn)單也最直觀的,下面還有幾種條件預(yù)處理也非常有用,可能大家并不一定熟悉,至少我剛開始寫代碼的時(shí)候就不太熟悉 :)
形式2:
#ifdef __DEBUG_MODE__
#define DEBUG_INFO show_debug_info();
#else
#define DEBUG_INFO
#endif
形式3:
#ifndef __DEBUG_MODE__
#define DEBUG_INFO
#else
#define DEBUG_INFO show_debug_info();
#endif
形式4:
#ifndef __NOT_DEBUG_MODE__
#define DEBUG_INFO
#else
#define DEBUG_INFO show_debug_info();
#endif
也許,有人會(huì)覺得上面兩種方式都是一樣,其實(shí),適時(shí)地巧妙地運(yùn)用會(huì)給自己帶來很多不必要的麻煩,特別是當(dāng)這些定義是開放給用戶去定義時(shí),往往不可預(yù)知用戶一定不會(huì)定義錯(cuò)誤,比如可能用戶會(huì)將#define __NOT_DEBUG_MODE__不小心
#define __NO_DEBUG_MODE__ 等等。
形式5:
#if __DEBUG_MODE__ = = 1
……
#else
……
#endif
形式6:
#if __DEBUG_MODE__ = = 1
……
#elif __DEBUG_MODE__ = = 2
……
#else
DEBUG MODE DEFINE ERROR!!!!
#endi
形式7:
#if defined __DEBUG_MODE__
……
#elif defined __NOT_DEBUG_MODE__
……
#else
DEBUG MODE DEFINE ERROR!!!!
#endif
3. 宏定義
有時(shí)候?yàn)榱顺绦?性能/簡(jiǎn)潔…)的要求,我們往往會(huì)在寫程序的時(shí)候?qū)懸恍┖甏a來滿足,這是個(gè)好的習(xí)慣,但千萬不要忘記了所有宏定義一定要加上括號(hào),來保證宏定義在任何地方展開都不會(huì)有語法/邏輯錯(cuò)誤,語法錯(cuò)誤還好,編譯器在編譯的時(shí)候會(huì)給你指出來,但是邏輯錯(cuò)誤,就……
注意:宏定義在預(yù)處理時(shí)只是對(duì)引用宏的地方做簡(jiǎn)單的字符替換!
對(duì)于表達(dá)式型的宏定義一定要加小括號(hào)();對(duì)于功能型的宏定義一定要加大括號(hào)。(不知道這里對(duì)于表達(dá)式和功能性的兩個(gè)限定詞是否準(zhǔn)確 :))
例如:
表達(dá)式宏定義:
有如下語句使用宏定義EXPRESS_MACRO c* EXPRESS_MACRO,其本意是c*(a+b)
(1),不加括號(hào)
#define EXPRESS_MACRO a+b
c* EXPRESS_MACRO, 展開后變成c*a+b
(2), 加括號(hào)
#define EXPRESS_MACRO (a+b)
c* EXPRESS_MACRO, 展開后變成c*(a+b)
有如下語句使用宏定義FUNCTION_MACRO
if(…)
FUNCTION_MACRO
其本意是
if(…)
{
c=a+b;
d=a*b;
}
(1),不加括號(hào)
#define TEST_MACRO c= a+b; d= a*b;
if(…)
FUNCTION_MACRO
展開后變成:
if(…)
c=a+b;
d=a*b;
很嚴(yán)重的邏輯錯(cuò)誤…
(2),加括號(hào)
#define TEST_MACRO {c= a+b; d= a*b;}
if(…)
FUNCTION_MACRO
展開后變成:
if(…)
{
c=a+b;
d=a*b;
}
本來宏定義的這些問題打算歸結(jié)到 (三),警惕潛在危險(xiǎn) 中去總結(jié)的,但考慮到開篇總的多寫一些內(nèi)容,就在這里一并總結(jié)了吧 :)
3.#define 與typedef
#define 在編譯預(yù)處理時(shí)進(jìn)行處理,不會(huì)做任何類型檢查
typedef 是屬于編譯的時(shí)候處理,編譯的時(shí)候會(huì)做類型檢查.br />