C言語の基礎
前へ 目次へ 次へ 

6 データ構造

6-1 構造体

 構造体とは、intやcharなどのデータ型を組み合わせて新しいデータ型として扱うことである。例えば、生徒の氏名、出席番号と電話番号を扱う場合、次のように変数を設定するのが基本的なやり方である。

char name[20];
int number;
int tel;

 しかし、これらのデータは1人分のデータであるから必ずまとめて処理されるます。 したがって、これらを1つのデータとして扱うことができると便利であるから、新しいデータ型を作ることにする。新しいデータ型の名前は、newtype(名前は自由につけることができる)とする。このnewtypeの宣言は次のようになる。

struct newtype {
  char name[20];
  int number;
  int tel;
};

 ここで、structが新しい型を定義するための命令である。このnewtypeという型を持つ変数を構造体変数といい、宣言するには次のようにする。構造体変数名はseitoとする。

struct newtype seito;

 構造体変数seitoにはname, number, telという要素が含まれている。

/* sample48.c */
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
    struct newtype{      /* ← 新しい型の定義 *1 */
        char name[20];
        int number;
        int tel;
    };
    struct newtype seito;    /* ← 新しい型の構造体変数の宣言 */
    char buff[80];
 
    printf("Name=");    gets(seito.name);    /* ← 要素の使用 */
    printf("Number=");  gets(buff);
    seito.number = atoi(buff);
    printf("Tel=");     gets(buff);
    seito.tel = atoi(buff);
    printf("No%d %s (%d)\n",seito.number, seito.name, seito.tel);
}

 新しい型の各要素を参照するには、構造体変数名と各要素名をピリオドでつなぐ。もし、40人分の変数を用意したければ、新しい型の宣言で次のように配列として宣言する。

struct newtype seito[40];

 例えば5番目の生徒のデータを参照したい場合は、次のようにする。

seito[5].name, seito[5].number, seito[5].tel

 C言語では新しいデータ型をタグといい、各要素のことをメンバという。

(1) 構造体の宣言方法

 構造体の定義・宣言方法には次のような種類がある。

@ タグ(新しいデータ型)の定義

struct タグ名 {メンバの並び};

A 構造体変数の宣言

struct タグ名 構造体変数名;

B @,Aを同時に行う

struct タグ名 {メンバの並び} 構造体変数名;

C タグの定義を行わないで構造体変数の宣言を行う

struct {メンバの並び} 構造体変数名;

 sample48.c の例では、@とAの方法で構造体を利用している。

 Bの方法を使用すると*1の部分は次のようになる。

struct newtype {
  name[20];
  number;
  tel;
} seito;

また、Cの方法を使用すると*1の部分は次のようになる。

struct {
  name[20];
  number;
  tel;
} seito;


(2) 構造体メンバーの参照

 構造体の各メンバーを利用するには、sample48.cにも示したように構造体変数名とメンバー名をピリオドでつないで使用する。

構造体変数名.メンバー名

 構造体変数も変数であるからポインタとして扱うこともできる。

/* sample49.c */
#include <stdio.h>
int main(void)
{
    struct xyz {
        int i;
        int j;
    };
    struct xyz abc, *pabc;
    pabc = &abc;
    pabc->i = 10;
    pabc->j = 20;
    printf("abc.i=%d abc.j=%d\n", pabc->i, pabc->j);
}

 構造体ポインタ変数でメンバを参照する場合には、ポインタ変数とメンバ名を->でつないで使用する。

構造体のポインタ変数名->メンバ名

 メモリには次のように領域が確保される。

構造体


(3) 構造体のデータ一括代入

 ANSI C規格で正式に認められた処理である。今までのC言語では、構造体の各メンバのデータを代入するには、それぞれ個別に行わなければならなかった。

struct {
  int i;
  int j;
} a, b;

 このような場合、構造体変数bのデータを構造体変数aに代入するには次のようにメンバ個別に行った。

a.i = b.i;
a.j = b.j;

 ANSI Cでは、構造体変数名どうしの代入が可能になった。上と同じ処理を次のように書くことができる。

a = b;


(4) 関数での構造体データの受け渡し

 他の変数と同じように、構造体変数を関数の引数及び返却値に指定することができる。

/* sample50.c */
#include <stdio.h>
struct date {    /* ← 構造体の定義 */
    int year;
    int month;
    int day;
};
int main(void)
{
    struct date nextday(struct date);    /* ← 関数の宣言 */
    struct date today, tomorrow;         /* ← 構造体変数の宣言 */
    today.year = 1992;
    today.month = 5;
    today.day = 17;
    tomorrow = nextday(today);            /* ← 関数の呼び出し */
    printf("%d/%d/%d\n",tomorrow.year, tomorrow.month, tomorrow.day);
}
struct date nextday(struct date now)      /* ← 構造体データを引数として受け取る */
{
    struct date next;
    next = now;
    next.day += 1;
    return(next);    /* ← 構造体データを返す */
}

 関数nextdayでは、struct date型の構造体変数を引数と返却値に利用している。


(5) フィールド

 変数に1か0の情報を持たすだけのためにshort型の変数を使うとそれだけでメモリを2バイト使ってしまう。情報としては1か0の1ビットであるからうまく利用すれば、short型の変数で16個の1か0の情報を格納する個とができる。これを行うのがフィールドである。

/* sample51.c */
#include <stdio.h>
struct {
    unsigned a: 1;
    unsigned b: 1;
    unsigned c: 1;
} flag;
int main(void)
{
    flag.a = 1;
    flag.b = 0;
    flag.c = 1;
    printf("a=%d b=%d c=%d\n",flag.a, flag.b, flag.c);
}

 フィールドの定義は構造体と同じである。メンバーのところでビット幅を指定するのが違うところである。

フィールド(メンバー)名:ビット幅


フィールド


6-2 共用体

 1つの共通領域を違ったデータ型として取り扱うことができる。

union tagname
  short a;
  char b;
  int c;
} xyz;

 共用体の定義には、unionを使う。定義方法は構造体と同じである。
 上の場合メモリには、次のように領域が確保される。

共用体

 各データの参照方法も構造体と同じである。


6-3 列挙型

 定義・宣言の方法は構造体と同じである。structの代わりにenumを使う。

enum number {ZERO, ONE, TWO, THREE} num;

 ZERO, ONE, TWO, THREE はそれぞれ列挙型定数である。それぞれ値としてZERO=0, ONE=1, TWO=2, THREE=3を持っている。
 最初の列挙型定数の値を0として、それ以降は1ずつ増えていく。また次のように値を定義することもできる。

enum number {ZERO, FIVE=5, SIX, SEVEN} num;

 それぞれ、ZERO = 0, FIVE = 5, SIX = 6, SEVEN = 7 の値を持つ。


前へ 目次へ 次へ 
Copyright © 2001 Hiroshi Masuda 

 

 

inserted by FC2 system