1

C プリプロセッサを使用して、C11 または C99 で goto ラベルをネストすることは可能ですか? 私のケースは、おそらく次のコードを見るとよくわかります。できれいにコンパイルされgcc -std=c99 -pedantic -Wall -Wextraます。

#include <stdio.h>

// Macro for mangling the identifier to avoid collisions
#define CTX_ID_(NAME) context_label_ ## NAME ## _
#define CTX_ID(NAME) CTX_ID_(NAME)

// The context keyword starts a block that can be exited with break (ID);
// Just syntactic sugar to keep it structured.
#define context(ID) \
    if (0) { CTX_ID(ID): ; } else

// Overloaded break keyword. Doesn't prevent using the plain break;    
#define break(ID) \
    do { goto CTX_ID(ID); } while (0)

// Example run
int main(void) {
    context (c) {
        while (1) {
            puts("Outer loop, visible.");
            while (1) {
                puts("Inner loop, visible.");
                break (c);
                puts("You won't see me.");
            }
        }
        puts("Nor me.");
    }
}

識別子 (この場合は c) を廃止しようとしています。ただし、変数とは異なり、goto ラベルは関数内で一意である必要があるため、ネスト/スコープすることはできません。goto ラベルとして使用できる C プリプロセッサで一意のスコープ識別子を実装することは可能ですか?

GCC はラベルのアドレス取得をサポートしていますが、ISO 標準の一部ではありません。また、オーバーヘッドと揮発性の問題により、特に setjmp を回避しようとしています。最後に、上記の構文の有用性が分からない場合は、try-catch 句や Python スタイルの with-expressions などを使用して、RAII のような機能を有効にすることを考えてください。

4

2 に答える 2

2

__LINE__マクロが便利になる可能性があると確信しています。スコープはありませんが、少なくともこの方法で一意のラベル名を生成できます。

ただし、これで問題が解決するかどうかはすぐにはわかりません。私は大胆にそれが解決できないと述べますが、誰かがやって来て私が間違っていることを証明する可能性があると確信しています!

于 2012-06-24T11:06:02.880 に答える
1

あなたのアイデアは素敵に見えますが、私が見逃す唯一のことはbreak(c)、関数内のどこでも発行できることです。2 つのマクロに次のようなものを追加します。

#define CONTEXT(ID)                                     \
    if (0) { CTX_ID(ID): ; }                            \
    else for (register bool CTX_ID(ID ## ID) = true;    \
              CTX_ID(ID ## ID);                         \
              CTX_ID(ID ## ID) = false)

#define BREAK(ID)                \
    do {                         \
       CTX_ID(ID ## ID) = false; \
       goto CTX_ID(ID);          \
   } while (0)

BREAK(c)依存ブロックの外で使用すると、構文エラーが発生します。私の経験forでは、ここで使用されているような変数は、最新のコンパイラによって簡単に最適化されます。

于 2012-06-24T16:42:49.413 に答える