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 のような機能を有効にすることを考えてください。