前回と似ているが、さらにめんどうな話だ。
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 件のコメント:
コメントを投稿
コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。
注: コメントを投稿できるのは、このブログのメンバーだけです。