構造体とは?

構造体は、プログラマが作れる構造を持たせた新しいデータ型といえます。
これによって、複数の情報を1つの変数で管理できるようになります。

具体的に、「名前と点数(整数)」のようなデータをそれぞれ2つ管理したい場合を考えてみましょう。 これまでの構造体を使わない方法では、 それらを記憶する変数を、次のように4つ用意する必要があります。

	char name1[10];	/* 1件目の名前記憶用 */	
	int idata1;	/* 1件目の点数記憶用 */

	char name2[10];	/* 2件目の名前記憶用 */	
	int idata2;	/* 2件目の点数記憶用 */

このような場合、「名前と点数(整数)」をまとめて、1つの変数で管理させる構造体を使うと次の ように2つの変数で済みます。

struct data_t {
	char name[10];	/* 名前 */
	int  idata;	/* 点数(整数) */
};

struct data_t  d1; /* 1件目の名前と点数 */
struct data_t  d2; /* 2件目の名前と点数 */

上記において、d1 と d2 のそれぞれは、nameとidataの構造を持っている変数です。
そして、d1 と d2 それぞれは struct data_tのデータ型です。
このstruct data_t型は、     の範囲で作っています。
この {}; の範囲で、nameとidataの名前を持つような構造を作っている部分を、 構造体の定義と呼びます。
ここで、name とidata は、構造体のメンバと呼びます。
そして、 data_t は、構造体を識別するための名前で、 構造体タグ名と呼びます。
構造体タグ名は、変数名を作る規則と同じで、名前を付けます。 (    の範囲で構造を設計していることになります。最後にセミコロンが必要です。)

上記例において、変数 d1 と d2は、「名前と点数(整数)」をまとめた全体を表現しています。
そして、仮に d1 = d2; を実行させれば、d2に記憶される「名前と点数(整数)」の 構造全体の情報が、d1 へコピーされます。 (実引数から仮引数へのセットもコピー処理になります。これらが可能なのは、同じ構造体の変数だけです)

しかし、d1 や d2に対して直接に比較や算術演算は使えません。C言語が基本的扱えるデータ型まで、 . 『ドットの記号』の構造体メンバ演算子で、メンバを指定する必要があります。
例えば、この例では d1のidataが80以上かを判定したい場合は、 d1.idata >= 80 という式になります。
d1.idata の表現は、構造体定義において idataをint型で作っているからです。

同様にこの例において、 d1.name の表現は、char * 型になります。 配列で作っているので、 d1.name = 値;のようには、配列名を変更する表現はエラーです。

d1.name[1] = 値; *(d1.name+1) = 値;の表現は可能ですが、nameメンバの 配列要素数が10個なので、9を超える表現をすると、期待した領域を超えたアクセスになってしまいます(正しく実行できません)。

同様に、構造体全体をキー入力したり、画面出力できる標準関数はありません。『 . 』の構造体メンバ演算子で、 各メンバを個別に指定して入出力する形態になります。 以下で、名前と点数を2件分入力して、表示する実行例とプログラム例を示します。

名前入力>suzuki
        点数入力>80
名前入力>yamada
        点数入力>85
suzuki 点数:80
yamada 点数:85
#include <stdio.h>

struct data_t {
	char name[10];	/* 名前 */
	int  idata;	/* 点数(整数) */
} a, b; /* 構造体定義直後で、変数 a と bを用意 */

main()
{
	printf("名前入力>");
	scanf("%s" , a.name);
	printf("\t点数入力>" );
	scanf("%d", & a.idata);

	printf("名前入力>");
	scanf("%s" , b.name);
	printf("\t点数入力>" );
	scanf("%d", & b.idata);

	printf("%s 点数:%d\n", a.name , a.idata);
	printf("%s 点数:%d\n", b.name , b.idata);
}

上記のように、構造体を定義しながら、 変数を用意することが可能です。 (この場合は、構造体タグ名を省略することができます。省略した時は、他の位置で同じ種類の変数は作れません。)
構造体のスコープ(struct data_t を使った変数宣言などができる範囲)は、変数宣言と同じで、 定義位置によってローカルやグローバルのスコープになります。
なお、構造体のメンバのネーミングは、構造体が異なれば同じ名前を何回使っても構いません。 また、変数と同じ名前になっても構わない規則になっています。