<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > C/C++中宏定義的經(jīng)典運用

C/C++中宏定義的經(jīng)典運用

作者: 時(shí)間:2016-12-01 來(lái)源:網(wǎng)絡(luò ) 收藏
在C語(yǔ)言中宏定義是比較有用的技巧,在Linux源碼中經(jīng)常使用一些宏定義,比如宏container_of()等都是經(jīng)典的宏定義表示方式。在C++不再主張使用宏定義,但是宏定義實(shí)際上卻是是一個(gè)非常有用的手段。實(shí)質(zhì)上宏定義能夠搞定的實(shí)現采用其它的實(shí)現也是可以的,宏定義的作用是簡(jiǎn)單的替代作用,掌握這個(gè)是理解的關(guān)鍵,以前在沒(méi)有代碼閱讀量的時(shí)候總是以為宏定義就是簡(jiǎn)單的定義一些常量什么的,實(shí)質(zhì)上不然,宏定義完全可以寫(xiě)成函數的形式,但是宏定義和函數有一定的差別,函數的調用一般采用棧的方式實(shí)現,這時(shí)候存在局部變量,形參、實(shí)參等問(wèn)題,如果不理解C語(yǔ)言的本質(zhì),很多時(shí)候非常容易搞錯,但是宏定義則不然,宏定義沒(méi)有調用的過(guò)程,宏的實(shí)現僅僅是一個(gè)替換過(guò)程,不用壓棧出棧,宏實(shí)現的類(lèi)似函數修改的就是當前區域中的變量,不是局部變量。這也是一些較深層次的問(wèn)題,在剛學(xué)習C語(yǔ)言的時(shí)候很多人只要看見(jiàn)類(lèi)似于函數的形式都認為是函數,實(shí)質(zhì)上不一定,很有可能就是采用宏定義實(shí)現的類(lèi)函數,這時(shí)候就可能導致所謂的形參實(shí)參問(wèn)題發(fā)生較大的變化。關(guān)于宏的問(wèn)題在面試筆試的過(guò)程中、寫(xiě)代碼的過(guò)程中都是非常有用的部分,我就不再做介紹。

今天看了一遍博客《Reduce C-language coding errors with X macros》,感覺(jué)文章寫(xiě)得非常的好,也對自己寫(xiě)代碼有了一定的幫助,所以就將該文章用我自己的語(yǔ)言,寫(xiě)出來(lái)和大家分享分享吧。

本文引用地址:http://dyxdggzs.com/article/201612/324488.htm

在嵌入式實(shí)時(shí)操作系統中,經(jīng)常將系統分成很多層次,很多個(gè)模塊,每一個(gè)模塊都有自己的初始化過(guò)程,這時(shí)候我們一般采用的形式如下所示:

typedef void(*p_func_t)(void);

enum
{
STATE_0,
STATE_1,
STATE_2,
...
STATE_M,
NUM_STATES
};

p_func_t inital_table[NUM_STATES]
{
func_0,
func_1,
func_2,
...
func_M,
};

這種實(shí)現方法是比較常見(jiàn)的實(shí)現方式,但是這種方法的缺點(diǎn)是所有的初始化過(guò)程是按照一定的順序的,而且不能隨機的初始化,因此如果在編碼的過(guò)程中將狀態(tài)號與初始化函數對應錯誤,將出現比較難以發(fā)現的錯誤,這種錯誤經(jīng)常出現,當然有些編譯器以及支持隨機的初始化過(guò)程,但是并不具有通用性,而且這種實(shí)現方式代碼比較多,能不能采用宏定義的方式簡(jiǎn)化代碼量呢?當然是可以的,采用類(lèi)似于函數的宏定義就可以實(shí)現,具體的實(shí)現如下:

typedef void(*p_func_t)(void);

#define STATE_TABLE
ENTRY(STATE_0,func_0)
ENTRY(STATE_1,func_1)
ENTRY(STATE_2,func_2)
ENTRY(STATE_3,func_3)
ENTRY(STATE_4,func_4)

enum{
#define ENTRY(a,b) a,
STATE_TABLE
#undef ENTRY
NUM_STATES
};

p_func_t inital_table[NUM_STATES] =
{
#define ENTRY(a,b) b,
STATE_TABLE
#undef ENTRY
};

上面這種實(shí)現方式的優(yōu)點(diǎn)是運用了宏定義簡(jiǎn)少代碼量。我做一個(gè)簡(jiǎn)要的分析,首先采用宏定義定義了一組ENYRT,其中包含兩個(gè)參數,分別是狀態(tài)號STATE_N,和狀態(tài)對應的初始化函數,這種實(shí)現方式能夠避免上面所謂的狀態(tài)號與函數對應錯誤的問(wèn)題,因為在宏定義的過(guò)程中一般都會(huì )認真的確定各種接口,對應好了只需要定義相關(guān)的函數就可以啦。在enum中采用了#define和#undef來(lái)限定這一組宏定義的作用范圍,在個(gè)作用域中,ENTRY(a,b)是表示“a,”,需要注意不能忽略a后的,因為這就是在enum中定義變量后要添加的符號,我想大家應該知道enum{a,b,c,d}每一個(gè)成員后面都包含","的特性的。也就是說(shuō)在這作用域中,ENTRY(a,b)被替換為"a,",那么這時(shí)候STATE_TABLE就被替換為STATE_0,STATE_1等,然后和NUM_STATES就組成了第一個(gè)例程中的enum結構。而在p_func_t jumptable[NUM_STATES]仍然采用了了STATE_TABLE,由于采用了#define和#undef限定了宏的作用范圍,這時(shí)的ENTRY(a,b)將被替代為“b,”,也就是func_0,func_1等,這樣也就完成了函數指針數組的初始化過(guò)程,這樣的初始化能夠減少狀態(tài)號與初始化函數對應出錯的情況。

這樣的實(shí)現也可以認為是宏定義的巧妙運用,但是這種方法還是存在一些問(wèn)題,因為采用#define 和#undef這種方法很可能導致錯誤的產(chǎn)生,因為很有可能不能很好的把握這個(gè)限定作用域的使用方法,這時(shí)候可以采用一種新的類(lèi)似函數的實(shí)現方法,可以讓STATE_TABLE帶一個(gè)參數,也就是采用類(lèi)似命令的形式定義相關(guān)的內容:

typedef void(*p_func_t)(void);

/*以下產(chǎn)生幾個(gè)常用的命令*/
/*enum產(chǎn)生*/
#define EXPAND_AS_ENUM(a,b) a,
/*初始化表產(chǎn)生*/
#define EXPAND_AS_INITTABLE(a,b) b,
/*聲明各個(gè)函數*/
#define EXPAND_AS_FUNCDEC(a,b) void b(void);

/*將STATE_TABLE的參數就是具體的命令*/
#define STATE_TABLE(ENTRY)
ENTRY(STATE_0,func_0)
ENTRY(STATE_1,func_1)
ENTRY(STATE_2,func_2)
ENTRY(STATE_3,func_3)
ENTRY(STATE_4,func_4)

/*定義enum*/
enum{
STATE_TABLE(EXPAND_AS_ENUM)
NUM_STATES
};

/*聲明各個(gè)函數*/
STATE_TABLE(EXPAND_AS_FUNCDEC)

/*初始化表*/
p_func_t inital_table[NUM_STATES] =
{
STATE_TABLE(EXPAND_AS_INITTABLE)
};

以上實(shí)現方法能夠較好的避免#define和#undef的限定作用域問(wèn)題,這實(shí)際上采用ENTRY作為參數傳遞給STATE_TABLE,然后ENTRY可用來(lái)實(shí)現不同的指令,這些指令的定義也是一系列的宏定義,這種實(shí)現架構能夠比較好的避免缺少聲明等問(wèn)題。同時(shí)也較少了錯誤的產(chǎn)生可能。


上一頁(yè) 1 2 下一頁(yè)

關(guān)鍵詞: CC++宏定義經(jīng)典運

評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>