前回と似ているが、さらにめんどうな話だ。
struct {
struct {
int aaa;
} bbb;
} ccc;
こんな形になっているときの、aaaのサイズを知りたい。
まずは、前回と同じようなプログラムを書いてみよう。
01: #include <stdio.h> 02: #include <inttypes.h> 03: 04: #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 05: #define M_SIZE(type, mem) sizeof(((type *)0)->mem) 06: #define M_ITEM(type, mem) { #mem, M_SIZE(type, mem) } 07: 08: struct aaa { 09: uint8_t item8; 10: uint64_t item64; 11: const char* itemc; 12: int16_t item16; 13: struct { 14: uint8_t item8; 15: uint64_t item64; 16: const char* itemc; 17: int16_t item16; 18: } itemst; 19: }; 20: 21: const struct { 22: const char *name; 23: size_t sz; 24: } DB[] = { 25: M_ITEM(struct aaa, item8), 26: M_ITEM(struct aaa, item64), 27: M_ITEM(struct aaa, itemc), 28: M_ITEM(struct aaa, item16), 29: M_ITEM(struct aaa, itemst), 30: }; 31: 32: 33: int main(void) 34: { 35: for (int lp = 0; lp < ARRAY_SIZE(DB); lp++) { 36: printf("name=%s: %lu\n", DB[lp].name, DB[lp].sz); 37: } 38: }
うちの環境だと、こうなった。
name=item8: 1
name=item64: 8
name=itemc: 8
name=item16: 2
name=itemst: 32
これだと、構造体まるまるのサイズになっている。
もし構造体の構成を変更してしまったら、DBに保存しているデータと互換性が無くなってしまう(あ、ここではDBに構造体のデータをまるごと残すという目標でやってます)。
もし、構造体メンバに構造体がいたとしても何とかしたいなら、その中身もまたシリアライズしなくてはならない。
ああ、シリアライズ地獄だ。。。
ここまでくると、もうマクロとか実装だけで解決するのでは無く、前処理をして、現在の構造体を処理するデータやコードを自動生成してもらって、それを埋め込みたくなってくる。
これで思い出すのが、protobufだ。
ずいぶん前にちょっとだけ調べたことがあるけれども、あのときはプロトコルのエンコード/デコードをする手段として探していたので、データ保存として見ていなかった。
protobuf自体は、もともとシリアライズする何かだったはずだ。
バイナリのサイズが大きくなりそうだから避けていたけど、もうLinuxでしか動かさない前提になってきたし、そもそもDBを使う時点でそこそこのストレージを積めるくらいには大きなプラットフォームだろうから、とにかく一般的な方法で楽に安全に解決させたい。
そういうわけで、次回からはprotobufをあまり力を入れずに調べていこう。
0 件のコメント:
コメントを投稿
コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。
注: コメントを投稿できるのは、このブログのメンバーだけです。