C言語編 目次

 関数設計

 

・関数名の命名規則
・プログラミングに出る!英単語

 ポインタ

 

・データ型とポインタ

 データ型

 

・char *とconst char *は違う
・符号付きと符号なし

 演算子

 

・三項演算子とデータ型の問題

 制御構文

 

・条件式で代入する
・三項演算子を使ったswitch

 構造体

 

・構造体のサイズとアライメント
・構造体メンバのサイズを知る

 配列

 

・配列使用時の注意
・配列の要素数を知る

 メモリ管理

 

・メモリスタック
・動的メモリ確保とメモリリーク

 モジュール設計

 

・モジュール分割
・汎用モジュールとアプリ依存モジュール

 パフォーマンス
  徹底チューニング

 


・どんな処理に時間がかかるのか
・ファイル入出力の効率化
・アルゴリズムを考える1
・アルゴリズムを考える2

 プリプロセッサの便利機能


・2重インクルード防止

 


トップページへ戻る

構造体メンバのサイズを知る

 はじめに次のサンプルを見てください。

#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バイトだけになります。構造体の実体がなくても、ポインタ変数だけあれば構造体メンバのサイズを取得することができます。