C の __COUNTER__ マクロの使い方

備忘録。

GCC や Clang で利用できる C の拡張機能 __COUNTER__ マクロについて。

概要

__COUNTER____FILE____LINE__ と同様の定義済みマクロ。ただし、参照するたびに展開結果が変わる。

初回は0に展開され、以降は展開するたびに 1, 2, 3……とインクリメントしていく。例えば以下のコードについて考える。

#include <stdio.h>

int main(void) {
  printf("%d %d %d\n", __COUNTER__, __COUNTER__, __COUNTER__);
  return 0;
}

このプログラムをコンパイルして実行すると以下の出力を得る。

0 1 2

ユースケース

トークン結合演算子と組み合わせて、一意な識別子を生成するのに便利。例えば以下の GEN_FOO は無名。

#define GEN_FOO(suffix) GEN_FOO_SUB(suffix)
#define GEN_FOO_SUB(suffix) foo##suffix

GEN_FOO(bar) // => foobar
GEN_FOO(__COUNTER__) // => foo0
GEN_FOO(__COUNTER__) // => foo1
GEN_FOO(__COUNTER__) // => foo2

以前に C で RSpec のような記法で書けるテストフレームワークを作った際、before/after を実現するために Nested function を利用し、この before/after に相当する関数に一意な名前を付けるためにこのテクニックを利用した。