第 6 回 構造体

本日の内容


このドキュメントは http://edu.net.c.dendai.ac.jp/ 上で公開されています。

6-1. 構造体

構造体の基礎

座標のように、複数の値を一つのものとして扱いたい場合があります。 C 言語では構造体という仕組みで扱うことができます。 まず、構造体の型を決め、その型の変数を宣言します。 例えば座標の構造体の型は次のように宣言されます(最後のセミコロン(;)は必 須です)。これは変数宣言ではなく、型の宣言です。


struct point {
  double x; 
  double y;
};

このようにすると point という構造体の型が作られます。 point は構造体の型であって、変数ではありません。 point 型の変数 p と q を宣言するには次のようにします。


struct point p,q;

宣言した変数は次のように使います。

各項目をアクセスする。

p.x=1.0;
printf("%f\n",p.y);
変数から変数へ代入する。

q=p;
printf("%f\n",q.x);
配列変数のように、宣言時には一括して初期化できる(プログラム実行中 はできない)

struct point p={1.0,2.0};

なお、二つの構造体の変数が一致しているかどうかは == で調べられませんの で、一つ一つ要素を比べるしかありません。

typedef

構造体 A を作っても、変数宣言は struct A x; とするしかあ りません。 (C++ ではちゃんと A x; と書けますが……) そのため struct を書かなくするために typedef という宣言があります。


typedef struct point {
  double x; 
  double y;
} POINT;

と宣言すると、この宣言以降、 struct point の代わりに POINT と書けば済 むようになります。 変数宣言は次のようになります。


POINT x,y;
POINT z={1.0,2.0};

これは関数の定義でも使えます。

構造体のポインタ

構造体のポインタの宣言は通常のポインタと同様です。


POINT *p;
POINT q={1.0,2.0};

q の番地を p に入れるのも同様です。


p=&q;

p の指す構造体の要素をアクセスする場合、 (*p).x とも書け ますが、これを p->x と書くこともできます。

構造体の配列

構造体の配列の取り扱いは、通常の配列の取り扱いと同様です。


POINT p[5];
int i;
for(i=0; i<5 ; i++){
  p[i].x=0.0;
  p[i].y=1.0;
}

関数とのやりとり

構造体は普通の変数と同様に関数と値をやりとりできます。 つまり、特にポインタなどを使用しなくてもよいということです。


#include <stdio.h>
typedef struct p {
    int x;
    int y;
} POINT;
POINT sub(POINT p){
  p.x--;
  p.y++;
  return p;
}
main(){
  POINT p={1,2},q;
  q=sub(p);
  printf("%d\n%d\n",q.x,q.y);
}

6-2. 演習

構造体 POINT を次のように定義します。


typedef struct point {
  double x;
  double y;
} POINT;

演習6-1

POINT 型の引数をもらい、原点からの距離を double 型で返す関数 distance を作りなさい。 そして、以下の main 関数によりその関数をテストしなさい。


#include <stdio.h>
typedef struct point {
  double x;
  double y;
} POINT;
double distance(POINT p);
main(){
  POINT p={3.0,4.0};
  printf("点 %f, %f と原点の距離は %f です。\n",p.x,p.y,distance(p));
}

ここで、 double distance(POINT p); はこのファイルで distance という関数を使用することを宣言する文です。 このように関数の使用を宣言する文をプロトタイプと言います。 distance 関数が同じプロジェクトの別ファイルである場合は、このように関 数を使用するファイル内でプロトタイプの宣言が必要になります。

演習6-2

POINT 型のポインタを引数とし、その引数の x 座標、y 座標とも 1/2 にする 関数 void half(POINT *p)を作りなさい。 そして、以下の main 関数によりその関数をテストしなさい。


#include <stdio.h>
typedef struct point {
  double x;
  double y;
} POINT;
void half(POINT *p);
main(){
  POINT p={6.0,8.0};
  printf("最初の点は %f, %f です。",p.x,p.y);
  half(&p);
  printf("半分の位置は %f, %f です。",p.x,p.y);
}

坂本直志 <sakamoto@c.dendai.ac.jp>
東京電機大学工学部情報通信工学科