2

循環中の複数行マクロを呼び出して、中断/継続したい。

複数行のマクロ定義で "do{...}while(0)" を使用すると、ブレーク/コンティニューは "do{...}while(0)" にのみ影響し、このマクロを呼び出す循環には影響しません。そのため、マルチマクロ定義で「if(1){...}」を使用することを検討しています。

#define EXIT_CIRCULATION() \
        if(1){ \
           break; \
        }

void func(){
    while(1){
       ...
       EXIT_CIRCULATION();
       ...
    }
}

しかし、インターネットで例が見つからないため、マクロ定義で「if(1){...}」を使用するのが良い方法であるかどうかは疑問です。

ありがとう!

4

3 に答える 3

10

あなたが次のようなものをコーディングする場合

 if (somecondition)
    EXIT_CIRCULATION();
 else
    break;

そうすると、マクロの展開は直感的に期待したとおりに動作しなくなります。はelseあなたに適用され、if (1)決して起こりません。

于 2012-11-26T06:35:35.063 に答える
2

このトリックの背後にある全体的なアイデアは;、不可欠な部分として終端も組み込んだ複数行 (つまり、複合) ステートメントを作成する方法を見つけることです。;これにより、誤って空のステートメントを導入することなく、マクロ呼び出しの後に使用する機会が得られます。

{ ... }で終わっていないため、通常の複文 inは機能しません;。で終わる C/C++ の唯一の複数行ステートメント;do/while. この要件を満たす C/C++ 文法のステートメントは他にありません。(これは不正確な主張です。以下の「追伸」を参照してください)

他のすべての場合 (あなたを含むif (1) {...}) では、マクロ呼び出しの後は、追加の独立したスタンドアロンの空のステートメント;と見なされます。これにより、 1 つのステートメントのみを必要とするコンテキスト(サイクルの真の分岐や本体など) で使用される場合、マクロ呼び出しの後に記述することができなくなります。;if-elsedo/while

たとえば、次のように定義すると

#define A() if (1) {}

このコードはコンパイルされません

do
  A();
while (1);

と入れ替わるので

do
  if (1) {}; /* <- two statements, not one */
while (1);

そして、それは実際には との間の2 つのステートメントです。間に2 つのステートメントを指定し、それらをラップせずに指定すると、構文エラーになります。dowhiledowhile{}

PS 訂正:実行可能な唯一do/whileの亜種であるという上記の主張は正しくありません。@Michael Burrの回答では、同じ目的でトリックを使用している別の適切なバリアントを見ることができます。ただし、主な原則は変わりません。else ((void) 0)

于 2012-11-26T07:03:26.627 に答える
2

これは、あなたが望むことを安全に行うと私が信じているマクロです:

#define EXIT_CIRCULATION()  \
            if (1) {        \
                /* some statements */   \
                break;                  \
            }                           \
            else                        \
                do {} while (0)

ifhere が と一致するという事実はelse、マクロが別の 内で安全に使用できることを意味しifelse句は do-nothing do/ステートメントであるため、複数行のマクロを/whileでラップするのと同様のプロパティを提供します。マクロなどは、通常のステートメントであるかのようにセミコロンで終了する必要があります。セミコロンを忘れると構文エラーになります。そして、それは別のまたは節の中でうまく機能します。dowhileifelse

そして、あなたにとって最も重要なこと (私が思うに) は、breakステートメントがマクロに飲み込まれないことです。マクロが使用されているループから抜け出します。

それが良いアイデアかどうかは、まったく別のことです。多くのプログラマーは、フロー制御ステートメントがマクロ内に隠されることを好みません (制御フローが完全にマクロ ユニット内にある場合を除きます)。

これが実際の動作です:

#include<stdio.h>
#include<stdlib.h>

#define EXIT_CIRCULATION()  \
            if (1) {        \
                puts("done.");          \
                break;                  \
            }                           \
            else                        \
                do {} while (0)

int main()
{
    int i = 0;

    for (i = 0; i < 10; ++i) {
        if (i  > 4)
            EXIT_CIRCULATION();
        else
            puts("working...");
    }

    printf("i == %d\n", i);

    return 0;
}

出力:

working...
working...
working...
working...
working...
done.
i == 5
于 2012-11-26T10:51:40.707 に答える