#define FREE1(x) do { free(x); x = NULL; } while (0);
#define FREE2(x) { free(x); x = NULL; }
これらのマクロの違いは何ですか?
#define FREE1(x) do { free(x); x = NULL; } while (0);
#define FREE2(x) { free(x); x = NULL; }
これらのマクロの違いは何ですか?
あなたの質問がdo/while
マクロのトリックに関するものである場合、違いはありません。なぜなら、最初のマクロ定義で明らかにエラーを犯し、トリックの目的を完全に無効にしたからです。;
の後にを置きwhole (0)
ます。適切な実装では、最初のマクロにafterを絶対に含めないでください。これがトリックの要点です。;
while (0)
do/while
今、このコードはコンパイルされません
if (condition)
FREE2(arg);
else
/* something else */;
このコードもコンパイルされません
do
FREE2(arg);
while (condition);
この手法のポイントは、do/while
このコードをコンパイルすることです。FREE1
ただし、前述のエラーのため、マクロでコンパイルされません。
ただし、最初のマクロを正しく定義すると
#define FREE1(x) do { free(x); x = NULL; } while (0)
// No `;` at the end!!!
最初のマクロは、上記のコード サンプルで完全に正常に動作します。これが実際に、do/while
マルチステートメント マクロでこの手法を使用する理由です。つまり、そのようなコンテキストで通常の関数を正しくかつ均一に機能させるためです。
PS補足として、そのようなすべての手法の目的は、複数のステートメントのグループを1つの複合ステートメントに変換することです。特定のケースでは、シーケンスを単一の式free(x); x = NULL;
として再実装できます。これにより、複数ステートメントのマクロ手法が不要になります。つまり、これ(free(x), x = NULL)
#define FREE3(x) (free(x), x = NULL)
同様に動作します。しかし、それは個人的な好みの問題です。
実際、Cに関しては違いはありません。
その理由は、末尾にセミコロンが含まれているためです。
#define FREE1(x) do { free(x); x = NULL; } while (0);
あなたが通常使用したい理由do...while(0)
はここで説明されています、あなたは一般的にそれをif...else
ブロックで使用したいということです:
if (...)
FREE(x);
else
...
しかし、上記の使用法とマクロを使用すると、これは次のようになります。
if (...)
do { free(x); x = NULL; } while (0);;
else
...
...と...
if (...)
{ free(x); x = NULL; };
else
...
...両方とも不正な形式です。
どちらも、C /C++マクロのDo-Whileおよびif-elseステートメントで説明されているセミコロンの問題を修正するための半ば焼きの試みです。
このマクロを定義するためのより良い方法は
#define FREE3(x) do { free(x); x = NULL; } while (0)
(末尾のセミコロンなし。)
これ:
#define FREE1(x) do { free(x); x = NULL; } while (0);
一度だけ実行されるため、次と同じです。
#define FREE2(x) { free(x); x = NULL; }
しかし、アセンブリ コードにはさらに分岐があります。最新のコンパイラがおそらくそれを最適化したとしても、生成されるアセンブリ コードでさえ、すべての確率で同じになります。