Index

HOME > プログラムTOP > C++




C++の基礎知識(9)

【構造体篇】

| ●構造体 | ●共用体 | ●ビットフィールド |
( 記述篇, データ型篇, 定数篇, 変数篇, 演算子篇, 関数篇, 制御文篇, ポインタ篇, クラス篇, 番外篇 )

sasaraan programming

Exposition

●構造体

 構造体は複数のデータ型をあわせ持つことができます。書式は以下の形式となります。タグ名と変数は用途に応じて省略が可能です。要素は省略はできませんが、異なったデータ型の要素をいくつでも設置することが可能です。宣言後は、通常の変数やポインタ、配列などと同じように扱うことができます。

struct タグ名 {
  要素1; 要素2; ...
} 変数1, 変数2, ... ;

// 基本的な用法
struct book {
    int year;
    char *title;
} ;
void main() {
    // 変数を宣言して代入
    struct book work1;
    work1.year = 1601;
    strcpy(work1.title, "Hamlet");
    // 変数宣言と同時に代入
    struct book work2 
            = {1604,"Othello"};
}
// 変数を指定して宣言
struct book {
    int year;
    char title[100];
} work1, work2;
// 宣言時に変数を初期化
struct book {
    int year;
    char title[100];
} work1 = {1601, "Hamlet"};
// 宣言時に配列を初期化
struct book {
    int year;
    char title[100];
} work[3] = {
    {1601, "Hamlet"},
    {1604, "Othello"},
    {1606, "Macbeth"}
} ;
// タグ名を省略
struct {
    int year;
    char title[100];
} book[1000];
// 構造体の入れ子
struct _author {
    char name[100];
    int born;
} ;
struct book {
    int year;
    char title[100]:
    struct _author author;
} ;
// 構造体のポインタ
struct book {
    int year;
    char title[100];
} work1;
void main() {
    struct book *p;
    // アドレスを代入
    p = &work1;
    // データを代入('->'を使用)
    p->year = 1606;
    strcpy(p->title, "Macbeth");
}
// 構造体と配列とポインタ
struct book {
    int year;
    char title[100];
} work[3] = {
    {1601, "Hamlet"},
    {1604, "Othello"},
    {1606, "Macbeth"}
} ;
void main() {
    struct book *p;
    p = work;    // ポインタ 
    p += 2;      // work[2] に移動
    // work[2]の値を変更
    p->year = 1605;
    strcpy(p->title, "King Rear");
}

●共用体

 共用体は、同じメモリ領域のデータを異なるデータ型で操作するためのものです。宣言や変数、ポインタ、配列などの扱いは構造体と同じです。
// 共用体の宣言
union udata
{
    __int32 n ;  //整数型データ(4bytes)
    char c[4];  //文字型(1byte)の配列(x4)
} 

【メモリ上の配置イメージ】
バイト : 1  2  3  4
要素n : 0x41 0x42 0x43 0x44
要素c : c[3] c[2] c[1] c[0]

 ・CPUによっては配置が逆順になります。
// 出力テスト
void main() {
    union udata u ;
    u.n = 0x41424344;
    printf("%d", u.n) ;    // =1094861636
    printf("%c", u.c[0]) ;  // ='D'
    printf("%c", u.c[1]) ;  // ='C'
    printf("%c", u.c[2]) ;  // ='B'
    printf("%c", u.c[3]) ;  // ='A'
} 

●ビットフィールド

 通常、メモリの操作は1バイト単位(= 8ビット)ですが、ビットフィールドでは1ビット単位(0か1)で操作することが可能です。宣言は構造体を利用して行います。この時、要素の末尾に割り当てるビット幅を指定します。

struct タグ名 {
  要素1:ビット幅1; 要素2:ビット幅2; ...
} 変数1, 変数2, ... ;

// ビットフィールドの宣言
struct datedata {
    unsigned year : 7;   // 0 ... 2^7-1=127 が使用可能 
    unsigned month : 4;  // 0 ... 2^4-1=15 が使用可能
    unsigned day : 5;    // 0 ... 2^5-1=31 が使用可能
    unsigned weekday : 3; // 0 ... 2^3-1=7 が使用可能
} ; 
○メモリ配置のイメージ
1バイト目2バイト目3バイト目
123456781234567812345...
yearmonthdayweekday   
 なお、ビット幅0の要素をはさむと、次の要素は自動的に次のバイトの頭へ移動します。(ビット・パディング)
// パディングつきビットフィールドの宣言
struct datedata {
    unsigned year : 7;   // 0 ... 2^7=127 が使用可能
    unsigned : 0       // パディング 
    unsigned month : 4;  // 0 ... 2^4=15 が使用可能
    unsigned day : 5;    // 0 ... 2^5=31 が使用可能
    unsigned weekday : 3; // 0 ... 2^3=7 が使用可能
} ;
○メモリ配置のイメージ
1バイト目2バイト目3バイト目
123456781234567812345...
year monthdayweekday  

www.sasaraan.net

(c) morijoh