do while 0 在巨集定義中的作用

2022-03-19 10:48:57 字數 1858 閱讀 1584

如果你是一名c程式設計師,你肯定熟悉巨集,它們非常的強大,如果正確使用可以讓你的工作事半功倍。然後,如果你在定義巨集時,很隨意沒有認真檢查,那麼它們可能使得你發狂,浪費n多時間。在很多c程式中,你可能看到許多看起來不是那麼直接的較為特殊的巨集定義。下面就是乙個例子:

1

#define _set_taks_state(tsk, state_value) \

2dowhile(0)

在linux核心和其他一些著名的c庫中有許多使用dowhile(0)的巨集定義。這種巨集的用途是什麼?有什麼好處?

coogle的robert love(先前從事linux核心開發)給我們解答如下:

dowhile(0)在c中是唯一的構造程式,讓你定義的巨集總是以相同的方式工作,這樣不管怎麼使用巨集(尤其在沒有使用大括號包圍呼叫巨集的語句),巨集後面的分號也是相同的效果。

這句話聽起來可能有些拗口,其實用一句話概括就是:使用dowhile(0)構造後的巨集不會受到大括號、分號等的影響,總是會按你期望的方式呼叫執行。

例如:

1

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

然後你可能這樣呼叫:

1 foo(wolf);

這將巨集擴充套件為:

bar(wolf);baz(wolf);

這的確是我們期望的正確的輸出。下面看看如果我們這樣呼叫:

1

if(!feral)

2 foo(wolf);

那麼擴充套件後可能就不是你所期望的結果。上面語句將可能擴充套件為:

1

if(!feral)

2bar(wolf);

3 baz(wolf);

顯而易見,這是錯誤的,也是大家經常容易犯的錯誤之一。

幾乎在所有的情況下,期望寫多語句巨集來達到正確的結果是不可能的。你不能讓巨集像函式一樣行為——在沒有do/while(0)的情況下。

如果我們使用dowhile(0)來重新定義,即:

1

#define foo(x) dowhile(0)

現在,該語句功能上等價於前者,do能確保大括號的邏輯能被執行,而while(0)能確保該邏輯只被執行一次,即與沒有迴圈時一樣。

對於上面的if語句,將會被擴充套件為:

1

if(!feral)

2dowhile(0);

從語義上講,它與下面的語句是等價的:

1

if(!feral)

這裡你可能感到迷惑不解了,為什麼不用大括號直接把巨集包圍起來呢?為什麼非得使用do/while(0)邏輯呢?

例如,我們用大括號來定義巨集:

1

#define foo(x)

這對於上面舉得if語句的確能被正確擴充套件,但是如果我們又如下的語句呼叫呢??

1

if(!feral)

2foo(wolf);

3else

4 bin(wolf);

巨集擴充套件之後將變成:

1

if(!feral);

5else

6 bin(wolf);

大家可以看出,這樣就語法有問題了。

總結:linux和其他**庫里的巨集都用do/while(0)來包圍執行邏輯,因為它能夠確保巨集的行為總是相同的,而不管**中使用了多少分號和大括號。

引自:

巨集定義中的do while 0

如果你是c 程式設計師,我有理由相信你用過,或者接觸過,至少聽說過mfc,在mfc的afx.h檔案裡面,你會發現很多巨集定義都是用了do.while 0 或do.while false 比如說 define afxassume cond do while 0 粗看我們就會覺得很奇怪,既然迴圈裡面只執...

巨集定義中的do while 0

我們都知道do while迴圈,但是在巨集定義中常常會出現dowhile 0 的用法,這樣的迴圈不是只執行一次嗎?不用do while也可以實現相同的功能呀,那麼為什麼要使用dowhile 0 呢?我們先來分析幾個例子 define fun x func1 x func2 x if true fun...

在巨集定義中使用 do while 0

巨集定義中的do.while 0 如果你是c 程式設計師,我有理由相信你用過,或者接觸過,至少聽說過mfc,在mfc的afx.h檔案裡面,你會發現很多巨集定義都是用了do.while 0 或do.while false 比如說 define afxassume cond do while 0 粗看我...