私はstruct
既存のプログラムに非常に大きな影響を与えています。この構造体には、多数のビットフィールドが含まれています。
その一部 (たとえば、150 フィールドのうち 10 フィールド) を保存したいと考えています。
サブクラスを保存するために使用するサンプル コードは次のとおりです。
typedef struct {int a;int b;char c} bigstruct;
typedef struct {int a;char c;} smallstruct;
void substruct(smallstruct *s,bigstruct *b) {
s->a = b->a;
s->c = b->c;
}
int save_struct(bigstruct *bs) {
smallstruct s;
substruct(&s,bs);
save_struct(s);
}
また、時々変更したいので、どの部分を選択するのが面倒でないかを願っています. 前に紹介した素朴なアプローチは非常に壊れやすく、維持できません。smallstruct
20 の異なるフィールドにスケールアップする場合、 と関数の両方でフィールドを変更する必要がありsubstruct
ます。
私は2つのより良いアプローチを考えました。残念ながら、どちらも外部のCILのようなツールを使用して構造体を解析する必要があります。
最初のアプローチは、substruct
関数を自動的に生成することです。の構造体を設定し、それを解析して のフィールドに従って関数smallstruct
を生成するプログラムを作成します。substruct
smallstruct
2 番目のアプローチは、(C パーサーを使用して) に関するメタ情報bigstruct
を作成し、構造体の特定のフィールドにアクセスできるようにするライブラリを作成することです。これは、Java のクラス リフレクションのアドホックな実装のようなものです。
たとえば、struct-alignment がないと仮定すると、struct に対して
struct st {
int a;
char c1:5;
char c2:3;
long d;
}
次のメタ情報を生成します。
int field2distance[] = {0,sizeof(int),sizeof(int),sizeof(int)+sizeof(char)}
int field2size[] = {sizeof(int),1,1,sizeof(long)}
int field2bitmask[] = {0,0x1F,0xE0,0};
char *fieldNames[] = {"a","c1","c2","d"};
この関数でi
thフィールドを取得します。
long getFieldData(void *strct,int i) {
int distance = field2distance[i];
int size = field2size[i];
int bitmask = field2bitmask[i];
void *ptr = ((char *)strct + distance);
long result;
switch (size) {
case 1: //char
result = *(char*)ptr;
break;
case 2: //short
result = *(short*)ptr;
...
}
if (bitmask == 0) return result;
return (result & bitmask) >> num_of_trailing_zeros(bitmask);
}
どちらの方法も余分な作業が必要ですが、パーサーがメイクファイルに含まれていれば、サブ構造体の変更は簡単です。
ただし、外部依存関係なしでそれを行いたいと思います。
誰もがより良いアイデアを持っていますか? 私のアイデアが良いところで、インターネット上で私のアイデアの利用可能な実装はありますか?