|
構造体メンバのサイズを知る
はじめに次のサンプルを見てください。
#include <stdio.h>
#include <stddef.h>
#include <string.h>
struct t_sample
{
char name[32];
char age[8];
char comment[64];
char reserve[10000];
};
int main(int argc, char *argv[])
{
FILE *file = NULL;
char l_comment[64 +1];
int err = 0;
memset(l_comment, 0, sizeof l_comment);
if (!err) if ((file = fopen("sample.dat", "r")) == NULL) err = 1;
if (!err) if (fseek(file, offsetof(t_sample, comment), SEEK_SET)) err =1;
if (!err) if (fread(l_comment, 64, 1, file) != 1) err = 1;
if (!err) printf("comment:%s", l_comment);
if (file) {fclose(file); file = NULL;}
return 0;
} |
ファイルsample.datには構造体t_sample型のデータが入っているものとして、そこからcommentメンバを読み込んで表示するプログラムです。commentを読み込む領域として、変数l_commentをローカル変数にとっています。
さて、ここで変数l_commentのサイズを64+1と固定にしていますが、これは構造体t_sampleのメンバcommentのサイズと合わせているものです。こういう風にプログラム中に固定値で値を書くのはよくありませんね。できればsizeof演算子を使って、構造体のメンバcommentのサイズを参照するようにしたほうが、見やすくて変更に強いプログラムになります。
ところで、sizeof演算子はデータ型や変数のサイズを取得することができますが、構造体のメンバはデータ型として参照することはできません。例えば、次のように書いたとするとコンパイルエラーになります。
char l_comment[sizeof(t_sample.comment) +1]; |
では、構造体のメンバのサイズを取得するにはどうすればいいでしょうか。sizeof演算子はデータ型だけでなく、変数に対しても使うことができます。構造体のメンバはデータ型としては参照できませんが、変数としては参照することができます。これを使うと、次のように書くことができます。
t_sample l_t_sample;
char l_comment[sizeof(l_t_sample.comment) +1]; |
t_sample型の変数を別に作って、そのメンバのサイズをとっているわけです。しかし、ただサイズを取りたいだけのために変数を別に確保するのはちょっと無駄が多いですね。特に構造体t_sampleは巨大なメンバreserveを持っているので、ローカル変数に取るだけでスタックを大量に消費してしまいます。このような場合は、次のようにポインタ変数を使います。
t_sample *l_t_sampleP = NULL;
char l_comment[sizeof(l_t_sampleP->comment) +1]; |
こうすると、t_sampleが巨大な構造体であったとしても、余分に使うのはポインタ変数のサイズ4バイトだけになります。構造体の実体がなくても、ポインタ変数だけあれば構造体メンバのサイズを取得することができます。
|