C語言中宏定義(#define)時do{}while(0)的價值

最近在新公司的代碼中發現處處用到do{...}while(0),google了一下,發現Stack Overflow上早有不少討論,總結了一下討論,加上本身的理解,do{...}while(0)的價值主要體如今:程序員

1. 增長代碼的適應性google

下面的宏定義沒有使用do{...}while(0)spa

#define FOO(x) foo(x); bar(x);

這樣宏定義,單獨調用不會出現問題,例如:code

FOO(100)

宏擴展後變成:blog

foo(x);bar(x);

 這樣調用FOO沒有任何問題,可是FOO(x)不能放入控制語句中,例如編譯器

if (condition)
    FOO(x);
else 
    ...;

通過宏擴展後,變成了it

if (condition)
    foo(x);bar(x);
else 
    ...;

這樣就致使了語法錯誤,語法錯誤並不可怕,在編譯階段就能發現,更致命的是他有可能致使邏輯錯誤,這種錯誤編譯器發現不了,一出這種問題,程序員就抓狂吧。例如:  io

if (condition)
    FOO(x);

這段代碼通過擴展後變成:編譯

if (condition)
    foo(x); bar(x);

這樣一來,不管condition是true仍是false,bar(x)都會被調用。有沒有被這煎熬過的兄弟啊?class

這時候do{...}while(0)的價值就體現出來了,修改一下FOO的定義

#define FOO(x) do { foo(x); bar(x); } while (0)

這樣FOO,放入控制語句中就沒有問題了。

也許有人說:把foo(x);bar(x)用大括號括起來不就好了嗎?好比這樣定義:

#define FOO(x) { foo(x); bar(x); }

再看下面代碼:

if (condition)
    FOO(x);
else 
    ...;

擴展後:

if (condition)
    {foo(x);bar(x);} ; //注意最後這個分號,語法錯誤
else 
    ...;

照樣語法錯誤;

2.增長代碼的擴展性

我理解的擴展性,主要是宏定義中還能夠引用其餘宏,好比:

#define FOO(x) do{OTHER_FOO(x)} while(0)
這樣咱們不用管OTHER_FOO是但語句仍是符合語句,都不會出現問題

3.增長代碼的靈活性

 靈活性主要體如今,咱們能夠從宏中break出來,例以下面的定義:

#define FOO(x)  do{ \
    foo(x);  \
    if(condition(x)) \
        break; \
    bar(x) \
    ..... \} while(0)
相關文章
相關標籤/搜索