構造体

構造体 (structure) は値の集まりです。
構文 struct tag { declarations... }; // タグ宣言
struct tag { declarations... } name; // タグ宣言と変数宣言
struct { declarations... } name; // 変数宣言 (無名構造体)
struct tag name; // 変数宣言

タグ宣言と変数宣言

構造体タグを宣言してから、そのタグを使って構造体変数を宣言します。
struct stag { int i; char* p; }; // タグ宣言
struct stag s1; // 変数宣言

構造体タグと構造体変数を同時に宣言することもできます。
struct stag { int i; char* p; } s1; // タグ宣言 + 変数宣言

タグを使用しないで「無名構造体 (アノニマス構造体)」を宣言することもできます。
struct { int i; char* p; } s1; // 変数宣言

struct キーワードを省略できるように、typedef が使用されることもよくあります。標準ライブラリの FILE 構造体はその一例です。
typedef struct { int i; char* p; } styp; // 型宣言
styp s2; // 変数宣言 (無名構造体)

構造体は入れ子にできます。
struct { int i; char* p; } stag1;
struct stag2 { struct stag1 a; struct stag1 b; }; // タグ宣言
struct stag2 ns1; // 変数宣言
struct stag2 ns2 = { {1,"a"}, {2,"b"} }; // 変数宣言 + 初期化
struct stag2 ns3 = {1,"a",2,"b"}; // 上と同じ

初期化

値リスト ({ } で囲んだ初期化子の並び) で初期値を指定できます。
struct stag { int i; char* p; } s1; // タグ宣言
struct stag s1 = { 12, "str" }; // 変数宣言 + 初期化
struct stag { int i; char* p; } s2 = { 12, "str" }; // タグ宣言 + 変数宣言 + 初期化

自動変数の構造体に初期化子を指定すると、配列と同様に、その構造体は静的変数と見なされます。

参照

メンバの参照

構造体のメンバを参照するには、メンバ参照演算子「.」を使用します。
struct { int i; char* p; } s1;
int i = s1.i;
char* p = s1.p;

構造体へのポインタからメンバを参照するには、メンバ間接参照演算子「->」を使用します。
struct stag { int i; char* p; } s1;
struct stag* ptr = &s1; // ptr は構造体へのポインタ
int i2 = ptr->i;
char* p2 = ptr->p;
char* p2a = (*s1).p; // 上と同じ

代入

構造体は、= 演算子で丸ごと代入 (コピー) できます。
struct stag { int i; char* p; } s1;
struct stag s3 = s1; // 構造体全体を代入
struct stag* ptr = &s1;
s3 = *ptr; // 構造体全体を代入

構造体を他の関数に渡す

関数の引数として構造体を受け取ったり、関数から戻り値として構造体を返すことができます。
struct stag { int i; char* p; };
struct stag func( struct stag arg ) {
  arg.i += 10;
  return( arg );
}

構造体そのものを渡す代わりに、構造体のアドレス (ポインタ) を受け渡すこともできます。構造体のサイズが大きい場合は、この方が高速です。ただし、構造体そのものを渡した場合とは異なり、ポインタで受け取った構造体の内容を変更すると呼び出し側でのその構造体の値も変化します。
struct stag* func( struct stag* arg ) {
  return( arg );
}