浅谈ド{…}while(0)マクロ定义における役割
もしあなたがCプログラマであれば、マクロに詳しいはずです。それらは非常に強いです。正しい使い方をすれば、あなたの仕事は大変なことになります。しかし、マクロを定義する時、勝手にチェックしていないと、彼らはあなたを狂わせ、N時間を無駄にしてしまうかもしれません。多くのCプログラムでは、直接的ではないように見える多くのマクロ定義が見られます。
次はその例です。
GoogleのRobert Love(以前Linuxカーネル開発に従事していた)は次のように答えてくれます。
ド{…}while(0)はCで唯一の構造プログラムであり、定義されたマクロはいつも同じように動作します。これはどんなにマクロを使っても(特に大きな括弧で囲まれてマクロを呼び出す文がない)、マクロの後のセミコロンも同じ効果です。
この言葉はちょっと言いにくいかもしれませんが、実用的な一言で言えば、do{…}while(0)を使ったマクロ定義は、大かっこやセミコロンなどの影響を受けず、いつも希望通りに実行を呼び出されます。
たとえば:
ほとんどの場合、多文宏大を書いて正しい結果を達成することは不可能です。マクロを関数のようにしてはいけません。do/while(0)がない場合。
もし私たちがdo{…}while(0)を使ってマクロを再定義したら、すなわち、
上のif文に対しては、次のように拡張されます。
例えば、大かっこでマクロを定義すると、次のようになります。
まとめ:Linuxと他のコード庫のマクロは、いずれもdo/while(0)で実行ロジックを包囲しています。マクロの動作が常に同じであることを保証できます。コードを呼び出しても、何分間と大かっこを使っています。
以上の浅谈ド{…}while(0)は、マクロの定义での役割は、小编が皆さんに共有している内容の全てです。
次はその例です。
#define __set_task_state(tsk, state_value) \
do { (tsk)->state = (state_value); } while (0)
Linuxカーネルや他の有名なCライブラリには、do{…}while(0)を使用したマクロ定義がたくさんあります。このマクロの用途は何ですか?何かメリットがありますか?GoogleのRobert Love(以前Linuxカーネル開発に従事していた)は次のように答えてくれます。
ド{…}while(0)はCで唯一の構造プログラムであり、定義されたマクロはいつも同じように動作します。これはどんなにマクロを使っても(特に大きな括弧で囲まれてマクロを呼び出す文がない)、マクロの後のセミコロンも同じ効果です。
この言葉はちょっと言いにくいかもしれませんが、実用的な一言で言えば、do{…}while(0)を使ったマクロ定義は、大かっこやセミコロンなどの影響を受けず、いつも希望通りに実行を呼び出されます。
たとえば:
#define foo(x) bar(x); baz(x)
その後、このように呼び出すことができます。
foo(wolf);
これはマクロによって拡張されます。
bar(wolf); baz(wolf);
これは確かに私たちが望む正確な輸出です。以下を見てみます。このように呼んだら、
if (!feral)
foo(wolf);
拡張したらあなたが望む結果ではないかもしれません。上の文は次のように拡張されます。
if (!feral)
bar(wolf);
baz(wolf);
明らかに、これは間違いであり、みんながよく犯しやすい間違いの一つでもある。ほとんどの場合、多文宏大を書いて正しい結果を達成することは不可能です。マクロを関数のようにしてはいけません。do/while(0)がない場合。
もし私たちがdo{…}while(0)を使ってマクロを再定義したら、すなわち、
#define foo(x) do { bar(x); baz(x); } while (0)
現在、この文の機能は前者に相当し、ドは大括弧内の論理が実行されることを保証し、while(0)はこの論理が一回だけ実行されることを確保することができます。すなわち、ループがない場合と同じです。上のif文に対しては、次のように拡張されます。
if (!feral)
do { bar(wolf); baz(wolf); } while (0);
意味的には、以下の語句と等価である。
if (!feral) {
bar(wolf);
baz(wolf);
}
ここは困惑しているかもしれませんが、なぜ大きな括弧を使わずに直接マクロを取り囲むのですか?なぜdo/while(0)ロジックを使わなければならないですか?例えば、大かっこでマクロを定義すると、次のようになります。
#define foo(x) { bar(x); baz(x); }
これは上に挙げたif文に対して確かに正しく拡張されていますが、もし次のような文言があるならば、
if (!feral)
foo(wolf);
else
bin(wolf);
マクロを拡張すると、次のようになります。
if (!feral) {
bar(wolf);
baz(wolf);
};
else
bin(wolf);
これは文法が間違っていることが分かります。まとめ:Linuxと他のコード庫のマクロは、いずれもdo/while(0)で実行ロジックを包囲しています。マクロの動作が常に同じであることを保証できます。コードを呼び出しても、何分間と大かっこを使っています。
以上の浅谈ド{…}while(0)は、マクロの定义での役割は、小编が皆さんに共有している内容の全てです。