3

C ヘッダー ファイルに値の列挙があります。各値が列挙値の 1 つに対応する追加の配列または値のグループを定義したいと考えています。基本的に、配列は、列挙された各値に関連する情報のルックアップ テーブルになります。ただし、コンパイル時にヘッダーファイルでこれを行いたいです。

これを達成するための良い方法は何ですか?

以下は、2 つの個別の列挙型または定義構造体を使用してそれを実現する方法の例です。op列挙型のみを使用してこれを達成するためのよりエレガントな方法はありますか?

enum op {
op1,
op2,
op3
};

enum op_information {
op1_info = 0xff,
op2_info = 0xf3,
op3_info = 0xc1
}

更新:参照を使用して配列を静的に定義する方法があれば、私にとって同様に貴重な助けになります。つまり、次のようにする代わりに:

ushort op_information = { 0xff, 0xf3, 0xc1 },

達成できるか

ushort op_information[3]
op_information[op.op1] = 0xff;
op_information[op.op2] = 0xf3;
op_information[op.op3] = 0xc1

コンパイル時に?

4

4 に答える 4

7

C99指定イニシャライザの使用:

ushort op_information[] = {
    [op1] = 0xff,
    [op2] = 0xf3,
    [op3] = 0xc1,
};
于 2013-09-05T19:28:57.997 に答える
1

古い GNU cpp トリックを使用できます。完全にマクロ呼び出しで構成されるインクルード ファイルを作成します。

/* opdefs.h */
OP(op1, 0xff)
OP(op2, 0xff)

次に、次の間にインクルードを使用して OP の定義と定義解除を繰り返して、必要な列挙型を作成します。

#define OP(Id, Val) Id,
enum op {
#include "opdefs.h"
};
#undef OP

// Handy for debugging, e.g. printf("%s", op_to_string[the_op]);
#define OP(Id, VaL) #I,
char op_to_string[] = {
#include "opdefs.h"
};
#undef OP

#define OP(Id, Val) Id ## _info = Val,
enum op_information {
#include "opdefs.h"
};
#undef OP

同じインクルードを使用すると、求める配列を生成することもできることがわかります。

添加

@Sebastian が提案したように、インクルード ファイルを別のマクロに置き換えることができます。

#define OP_DEFS \
OP(op1, 0xff) \
OP(op2, 0xff)

#define OP(Id, Val) Id,
enum op { OP_DEFS };
#undef OP

#define OP(Id, VaL) #I,
char op_to_string[] = { OP_DEFS };
#undef OP

#define OP(Id, Val) Id ## _info = Val,
enum op_information { OP_DEFS };
#undef OP

一般に、多くの OP 定義がある場合、または複数のソースからそれらを使用する必要がある場合は、インクルード ファイル メソッドの方がクリーンです。マクロ メソッドは、1 つのファイルのみの短いリストに対してよりクリーンです。

于 2013-09-05T19:49:43.723 に答える
0

何をするにしても、セルフテストが必要になる場合があります。セルフテストにアサートを使用して、デバッグ ビルドでのみテストを実行します。

enum op {
    op1,
    op2,
    op3,
};

enum op_information {
    op1_info = 0xff,
    op2_info = 0xf3,
    op3_info = 0xc1,
};

ushort op_information = { op1_info, op2_info, op3_info };

// then somewhere, e.g. in a function called _OnBootup():
assert(op1_info == op_information[op1]);
assert(op2_info == op_information[op2]);
assert(op3_info == op_information[op3]);

また、上記のような非常に退屈で非常にデータ駆動型のものについては、通常、適切な C コードを記述する Python プログラムを作成します。凍結された標準コーデックのデコーダーを作成している場合など、本当に固定されている場合は、実際にそれを行う必要はありません。しかし、列挙型と一致する値が (R&D 中のように) 流動的であり、すべてを最新の状態に保つとエラーが発生しやすい場合は、op の名前と値を Python 辞書に入れ、Python コードですべてのボイラープレート C を生成します。コード。(もちろん、私は Python を使用していますが、好きなものを使用する必要があります。)

于 2013-09-05T19:49:23.690 に答える