01: プログラミング言語とは何か 02: 0から99まで印字するプログラムの解説 03: Pythonで書くと... 04: 変数と関数 05: 条件分岐とループ 06: プリプロセス 07: ポインタと配列1 08: ポインタと配列2 09: ポインタと配列3 0A: 文字列 0B: 多次元配列 0C: ファイル入出力 0D: 構造体 0E: コマンドライン引数 0F: 数値を読み込んで総和と平均を表示するプログラム 10: 数値を読み込んで総和と平均を表示するPythonプログラム 11:【番外編】文章中の単語を出現頻度順に表示するプログラム 12:【番外編】コマンドライン引数を処理するイディオム 13:【番外編】C言語でクロージャを実装する
構造体は,既存の型を組み合わせて新しい型を作るC言語の能力である.例えば2次元のベクトルをいつも
として扱うのは好ましくない.一方,
とすることは好ましい.なぜならば,構造体はほかの型と同じように,コピーを取ったり,アドレスを調べたり,サイズを調べたりすることが出来るからである.上述のようにpが定義されていれば,
のようにpの内容をそっくりそのままqへコピーすることが出来る.構造体の中身へは次のようにピリオドを使ってアクセスする.
構造体はsizeofでサイズを調べられるので,callocで配列を確保することも出来る.
これでpoint構造体100個からなる配列が確保できる.または,自動変数として
という確保の仕方もある.
構造体は,自分自身を除けば,任意の型を構成要素にすることが出来る.よく使われる構造体には,配列とそのサイズをまとめたものがある.例えば次の通り.
(標準Cの仕様の虚を突いて,可変長構造体というものを使うプログラマがいる.可変長構造体はC++で正式に禁止された.)
構造体はコピーできるので,関数の引数にも戻り値にも使える.いちいちstructと書くのは面倒なのでtypedefを使おう.
構造体が大きくなってくると,ベテランプログラマから,こんな書き方をするといちいちコピーが発生して効率が悪いと言われる.これは真実であるが,ポインタ渡し(参照渡し)にして効率を稼いでも,プログラムの可読性は全く上がらない(むしろ下がる)ので,初心者の間はわざと構造体のまま(参照にせず)受け渡しをするのがよい.この問題(関数をまたぐ構造体のやりとりに関する効率と可読性の問題)の本質的な解決にはC++0xが必要である.
構造体をいきなりprintfで出力したり,sscanfで文字列から復元したりすることは出来ない.構造体をファイルに出力したいときは,各要素ごとに出力する必要がある.構造体を出力する関数を書いておくと便利である.例えば次の通り.
自己参照構造体とは,自分自身へのポインタを含む構造体のことである.残念ながら,C言語は再帰関数をSchemeほどうまく扱えないため,自己参照構造体は宝の持ち腐れになる可能性が高い.教科書的な知識として知っておくことはよいことだが,実際に使う場面はかなり少ない.詳しくはK&R2を参照.
double p[2] = { 1.0, 2.0 };
として扱うのは好ましくない.一方,
struct point {
double x, y;
};
struct point p = { 1.0, 2.0 };
とすることは好ましい.なぜならば,構造体はほかの型と同じように,コピーを取ったり,アドレスを調べたり,サイズを調べたりすることが出来るからである.上述のようにpが定義されていれば,
struct point q = p;
のようにpの内容をそっくりそのままqへコピーすることが出来る.構造体の中身へは次のようにピリオドを使ってアクセスする.
printf("(%f, %f)\n", p.x, p.y);
構造体はsizeofでサイズを調べられるので,callocで配列を確保することも出来る.
struct point *pa = calloc(100, sizeof(struct point));
これでpoint構造体100個からなる配列が確保できる.または,自動変数として
struct point pa[100];
という確保の仕方もある.
構造体は,自分自身を除けば,任意の型を構成要素にすることが出来る.よく使われる構造体には,配列とそのサイズをまとめたものがある.例えば次の通り.
struct double_array {
int size_of_array;
double *array;
};
(標準Cの仕様の虚を突いて,可変長構造体というものを使うプログラマがいる.可変長構造体はC++で正式に禁止された.)
構造体はコピーできるので,関数の引数にも戻り値にも使える.いちいちstructと書くのは面倒なのでtypedefを使おう.
#include <math.h>
typedef struct point POINT;
POINT rotate_point(POINT p, double theta) {
POINT ret;
ret.x = cos(theta) * p.x - sin(theta) * p.y;
ret.y = sin(theta) * p.x + cos(theta) *p.y;
return ret;
}
構造体が大きくなってくると,ベテランプログラマから,こんな書き方をするといちいちコピーが発生して効率が悪いと言われる.これは真実であるが,ポインタ渡し(参照渡し)にして効率を稼いでも,プログラムの可読性は全く上がらない(むしろ下がる)ので,初心者の間はわざと構造体のまま(参照にせず)受け渡しをするのがよい.この問題(関数をまたぐ構造体のやりとりに関する効率と可読性の問題)の本質的な解決にはC++0xが必要である.
構造体をいきなりprintfで出力したり,sscanfで文字列から復元したりすることは出来ない.構造体をファイルに出力したいときは,各要素ごとに出力する必要がある.構造体を出力する関数を書いておくと便利である.例えば次の通り.
void print_point(POINT p) {
printf("(%f, %f)", p.x, p.y);
}
自己参照構造体とは,自分自身へのポインタを含む構造体のことである.残念ながら,C言語は再帰関数をSchemeほどうまく扱えないため,自己参照構造体は宝の持ち腐れになる可能性が高い.教科書的な知識として知っておくことはよいことだが,実際に使う場面はかなり少ない.詳しくはK&R2を参照.