C99 では、配列初期化子 (とりわけ) が、配列のどの要素を正の整数指定子 ($6.7.8.6、$6.7.8.17) で設定するかを指定できます。たとえば、次のようになります。
const char *foo[] = {[2] = "foo", [1] = "bar", [0] = "baz"};
私は以前にこれを使用して、列挙型から文字列へのテーブルを次のように作成しました。
enum {THING_FOO = 0, THING_BAR, THING_BAZ};
const char *table[] = {
[THING_FOO] = "foo",
[THING_BAR] = "bar",
[THING_BAZ] = "baz"
}
ただし、現在、コードが c89 に準拠しているという要件の下で作業しています。
私はプリプロセッサの魔法を調べました (たとえば、ここのように) が、列挙型シンボルのコピーではなく、文字列を任意にする必要があります。
するだけでは不十分
enum {THING_FOO = 0, THING_BAR, THING_BAZ};
const char *table[] = {"foo", "bar", "baz"};
将来、列挙要素を追加する必要があるためです。c99 メソッドを使用すると、テーブルに NULL ポインターが発生し、問題が発生した場合にデバッグが容易になります。このメソッドを使用して文字列テーブルを更新するのを忘れると、デバッグが困難なセグメンテーション違反が発生します。また、とにかくオフセットを覚えておく必要がある場合、シンボルを持つという点が無効になります。
宣言が関数内にある場合、次のように目的の効果を達成できます。
enum {THING_FOO = 0, THING_BAR, THING_BAZ, NUM_THINGS};
void foo(void)
{
static const char *table[NUM_THINGS];
table[THING_FOO] = "foo";
table[THING_BAR] = "bar";
table[THING_BAZ] = "baz";
/* ... */
}
ただし、少なくとも ではgcc
、これは最適化されません。
c89 でそのような文字列テーブルを宣言する方法はありますか? (組み立てには問題ありません。)