検索すると、この手の情報はたくさん出てくるのだが、自分でやってみたら書いてみたくなっても仕方なかろう?
サイズをしらべると言えば、sizeof演算子だ。
ただ、これは構造体のメンバを直接指定することができない・・・というよりも、C言語として、構造体の型のメンバだけを表す方法が無いのだと思う。
01: struct aaa { 02: uint8_t item8; 03: uint64_t item64; 04: const char* itemc; 05: int16_t item16; 06: };
こんな構造体があったとして、たとえばitem64だけを指す方法が無い。
インスタンスになってしまえばよいのだが、sizeofしたいだけなのインスタンスを作るのは避けたい。
じゃあどうするかというと、C言語としてインスタンスのように見えるものを使えばよい。
というわけで、適当な数字を「これはstruct aaa型のアドレスなんです!」と主張して、そのポインタのメンバをsizeofしてしまうわけだ。
#define M_SIZE(type, mem) sizeof(((type *)0)->mem)
こんなマクロを作って、
M_SIZE(struct aaa, item64)
とすると、
sizeof(((struct aaa*)0)->item64)
と展開される。
意味としては、アドレス0にstruct aaa型のメモリが入っていると見なしているだけだ。
アドレスにアクセスするわけではないので、0じゃなくても、100でも1000でもよい。
急にこの話が出てきたのは、lmdbと関係している。
いま、構造体のデータをlmdbでがさっとメモリダンプ的に保存させているのだが、構造体の構成が変わるたびに前のDBが使えなくなってしまうので、そろそろ何とかしたいと考えている。
やるなら、各メンバごとにkey/dataで保存させていくしか無かろう。
無いのだが、書き直すのがめんどくさい。
なるべく多く書かずにやらせたいわけだ。
lmdbは、keyもdataもMDB_val型を使っている。
MDB_val型は、サイズとデータを持つ構造体だ。
keyにつける名前はバイナリでも文字列でも何でもよいのだが、構造体であればメンバ名にするのがよいだろう。
keyのサイズはstrlen()で出せるからよいとして、あとはdataのサイズだ。
これを機械的に出したいなら、上記のマクロのようなものを作ってしまうのがよかろう。
そして、key名もdataサイズもメンバ名で取り出せるなら、こんなものを用意するとよいか。
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) #define M_SIZE(type, mem) sizeof(((type *)0)->mem) #define M_ITEM(type, mem) { #mem, M_SIZE(type, mem) } struct aaa { uint8_t item8; uint64_t item64; const char* itemc; int16_t item16; }; const struct { const char *name; size_t sz; } DB[] = { M_ITEM(struct aaa, item8), M_ITEM(struct aaa, item64), M_ITEM(struct aaa, itemc), M_ITEM(struct aaa, item16) }; int main(void) { for (int lp = 0; lp < ARRAY_SIZE(DB); lp++) { printf("name=%s: %lu\n", DB[lp].name, DB[lp].sz); } }
まあ、そこまで悪くはないかな。
0 件のコメント:
コメントを投稿
コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。
注: コメントを投稿できるのは、このブログのメンバーだけです。