構造体の基本

昔のC言語(*.c) のプログラムで、構造体の基本を説明します。
拡張子が *.c と *.cpp では構造体の扱い方が異なるらしく、*.c のソースプログラムで構造体の基礎を説明しましょう。

前田稔の超初心者のプログラム入門

プログラムの説明

  1. Set UP で説明した BAT ファイル(CLI.BAT)では *.c をコンパイル出来ません。
    いまさら拡張子が *.c のプログラムをコンパイルするとは思わなかったのですが、構造体を説明するにあたって必要になりました。
    C.BAT は CLI.BAT から /CLR スイッチを削除しただけですが。 (^_^;)
    vista & Visual Studio .NET2005 で実行を確認しました。
    ファイル名 説明
    C.BAT C.BAT のソースコード
  2. 本題の構造体の基礎を説明するプログラム(Main.c)です。
    構造体は関連する幾つかの項目を struct としてまとめて定義したものです。
    構造体は元々 COBOL 言語でレコード転送をするときに使われていました。
    レコードは、例えば名前,住所,生年月日,成績などの一人分のデータで構成されます。
    レコード転送とは、外部記憶装置(HDD や MT など)とメモリの間で「変換しないでそのまま転送」する方法で、大量のレコードを処理するときに使われます。
    レコード転送の基本は レコードの入出力 を参照して下さい。
    今回は v1, v2 とその和を格納する sum を構造体として定義しています。
    data は構造体の名前で、data に含まれるアイテムは data.v1 のように「.」を付けて参照します。
    プログラムの内容は、見ていただければ解ると思うので省略させていただきます。 (^_^;)
    _getch(); はコンソールの表示を確認するために追加したコードです。
    必要なければ <conio.h> と共に削除して下さい。
    /*★ 構造体(struct) のテスト  Main.c    前田 稔 ★*/
    #include <stdio.h>
    #include <conio.h>
    
    struct
    {
        int     v1;
        int     v2;
        int     sum;
    }   data;
    
    int main(void)
    {
        data.v1 = 10;
        data.v2 = 20;
        data.sum = data.v1 + data.v2;
        printf("data.v1= %d,  data.v2= %d,  data.sum= %d\n", data.v1, data.v2, data.sum);
        _getch();
        return 0;
    }
    
  3. 構造体もこれで終われば簡単なのですが、この後まるで七変化のように複雑怪奇に変化して行きます。 (^_^;)
    object class も元はと言えば「構造体が変化したなれの果て」と言えば驚かれるでしょうか。 0(^_^)0
    構造体を本当に理解しているプログラマなんて、何人いるのでしょう。
    今度は構造体の形を宣言するコードと、構造体の領域を定義するコードを分けてみました。
    拡張子が *.c のプログラムでは、次のように書くとエラーになります。
    struct TData data; //OK
    TData data; //Error
    所が不思議なことに拡張子が *.cpp のプログラムでは通るのです。
    このことを確認したいがために *.c のプログラム環境を整えました。 (^◇^;)
    /*★ 構造体(struct) のテスト  Main.c    前田 稔 ★*/
    #include <stdio.h>
    #include <conio.h>
    
    struct  TData
    {
        int     v1;
        int     v2;
        int     sum;
    };
    struct  TData   data;   //OK
    //TData data;             //Error
    
    int main(void)
    {
        data.v1 = 10;
        data.v2 = 20;
        data.sum = data.v1 + data.v2;
        printf("data.v1= %d,  data.v2= %d,  data.sum= %d\n", data.v1, data.v2, data.sum);
        _getch();
        return 0;
    }
    
  4. その次に登場するのが typedef です。
    typedef で構造体を宣言すると、頭の struct を省略することが出来ます。
    おかげでソースコードを見ただけでは、構造体なのか構造体では無いのかが識別出来なくなりました。 (^_^;)
    /*★ 構造体(struct) のテスト  Main.c   前田 稔 ★*/
    #include <stdio.h>
    #include <conio.h>
    
    typedef struct
    {   int     v1;
        int     v2;
        int     sum;
    }   TData;
    TData   data;
    
    int main(void)
    {
        data.v1 = 30;
        data.v2 = 40;
        data.sum = data.v1 + data.v2;
        printf("data.v1= %d,  data.v2= %d,  data.sum= %d\n", data.v1, data.v2, data.sum);
        _getch();
        return 0;
    }
    
  5. 次の定義が構造体なのか構造体では無いのかを当てて下さい。 (^_^;)
    ソースコードを見ただけでは、識別出来ないでしょう。
        POINT       pnt;
        BYTE        bdata;
        WORD        wdata;
        UINT        val;
        LONG        ldata;
        SIZE        siz;
        RECT        rect;
        PAINTSTRUCT ps;
        HDC         hdc;
        MSG         msg;
        
  6. 実は Windows Program では、構造体が typedef で非常に多く宣言されています。
    その中から馴染み深いものを幾つか紹介しましょう。
    ウインドウの座標などを記録する POINT 構造体です。
    NEAR *NPPOINT, FAR *LPPOINT は16ビットの名残で、現在では意味がありません。
    typedef struct tagPOINT
    {
        LONG  x;
        LONG  y;
    } POINT, *PPOINT, NEAR *NPPOINT, FAR *LPPOINT;
    
    矩形領域を記録する RECT 構造体です。
    typedef struct tagRECT
    {
        LONG    left;
        LONG    top;
        LONG    right;
        LONG    bottom;
    } RECT, *PRECT, NEAR *NPRECT, FAR *LPRECT;
    
    大きさを記録する SIZE 構造体です。
    typedef struct tagSIZE
    {   LONG        cx;
        LONG        cy;
    } SIZE, *PSIZE, *LPSIZE;
    
    BMP ファイルのヘッダ形式を定義した構造体です。
    これ以外にも Windows のヘッダファイルを調べれば腐るほど見つかるはずです。
    typedef struct tagBITMAPFILEHEADER
    {
        WORD    bfType;         //"BM"の2バイト
        DWORD   bfSize;         //ファイルのサイズ
        WORD    bfReserved1;
        WORD    bfReserved2;
        DWORD   bfOffBits;      //ファイルの先頭からビット配列までのオフセット値
    } BITMAPFILEHEADER; 
    
    typedef struct tagBITMAPINFOHEADER
    {
        DWORD  biSize;          //構造体の大きさが入ります
        LONG   biWidth;         //ビットマップの幅
        LONG   biHeight;        //ビットマップの高さ
        WORD   biPlanes;        //プレーンの数ですが1でなくてはいけません
        WORD   biBitCount;      //ピクセルあたりの色数。1,4,8,24のいずれか
        DWORD  biCompression;   //圧縮方式を示します。0で圧縮なし
        DWORD  biSizeImage;     //ビットマップビットのサイズ。圧縮の時のみ必要
        LONG   biXPelsPerMeter; //水平解像度を示します。ピクセル数/インチ
        LONG   biYPelsPerMeter; //垂直解像度を示します
        DWORD  biClrUsed;       //イメージで使われている色数
        DWORD  biClrImportant;  //イメージで使われている重要な色の数
    } BITMAPINFOHEADER;
    

超初心者のプログラム入門(C/C++)