構造体へのポインタは関数の引数や戻り値によく使われる.なぜか?
復習: 関数が処理される前に,呼び出し側で引数に書いた内容(値)が, 関数側にある別の領域(仮引数)にコピーされ,また,関数の処理が終了した後に, 戻り値になる内容は,関数側から呼び出し側へコピーされる.
構造体自身を引数や戻り値にした場合は,コピーされる量が多くなりがちで, 関数の本来の処理量に比べてその処理量が無視できない. example43.c程度の構造体ならば気にしなくて良いが, もっと複雑な場合だと問題となる.
構造体を引数や戻り値にすると見通しの良いプログラムを書くことができるが, ある程度以上大きな構造体の場合は,通常,処理量の少なさ(=処理速度)を重視して, ポインタを用いてデータのやり取りを行う.構造体自身が大きくても, そのポインタの大きさは同じなので, ポインタを用いることで本来以外の処理の増加による効率の低下を避けることができる.
「値渡し+戻り値」と「ポインタによる参照渡し」の比較(double型の場合)
引数や戻り値の型がintやdoubleではなく,サイズがもっと大きくなると, データの引き渡しのための処理量が増える. 一方,ポインタを引き渡す場合は,指す型が変っても処理量はは同じ.
「値渡し+戻り値」と「ポインタによる参照渡し」の比較(complex型の場合)
struct タグ名 *ポインタ変数名; 新型名 *ポインタ変数名;
(例) struct vector *pv; complex *x, *y, *z;関数の戻り値や引数の場合も同じように宣言できる.
(例) complex * cAdd(complex *po, complex *p1, complex *p2) { ..... }
(*ポインタ).メンバ ←(等価)→ ポインタ->メンバ注意: 「*ポインタ.メンバ」と書くと「*(ポインタ.メンバ)」の意味.
(例) typedef struct { double re; double im; } complex; complex a, *p; p = &a; p->re = 1.0; p->im = 2.0; printf("a = %f + %fi\n", a.re, a.im);
int main(void) { fraction x1, x2, x3, t1, t2; fracMake(&x1, 3, 4); fracMake(&x2, 5, -6); printf("x1 = "); fracPrint(&x1); printf("\n"); printf("x2 = "); fracPrint(&x2); printf("\n"); fracAdd(&x3, &x1, &x2); printf("x1 + x2 = "); fracPrint(&x3); printf("\n"); fracMul(&x3, &x1, &x2); printf("x1 * x2 = "); fracPrint(&x3); printf("\n"); fracAdd(&x3, fracMul(&t1, &x1, &x1), fracMul(&t2, &x2, &x2)); printf("x1*x1 + x2*x2 = "); fracPrint(&x3); printf("\n"); return 0; }
struct タグ名 { 型名1 メンバ名1; 型名2 メンバ名2; ...; }; typedef struct タグ名 * 型名;
typedef struct { 型名1 メンバ名1; 型名2 メンバ名2; ...; } * 型名;
typedef struct { int n; /* 分子 (numerator) */ int d; /* 分母 (denominator) */ } *fractionp; int main(void) { fractionp x1, x2, x3, t1, t2; x1 = fracAlloc(1); x2 = fracAlloc(1); x3 = fracAlloc(1); t1 = fracAlloc(1); t2 = fracAlloc(1); fracMake(x1, 3, 4); fracMake(x2, 5, -6); printf("x1 = "); fracPrint(x1); printf("\n"); printf("x2 = "); fracPrint(x2); printf("\n"); fracAdd(x3, x1, x2); printf("x1 + x2 = "); fracPrint(x3); printf("\n"); fracMul(x3, x1, x2); printf("x1 * x2 = "); fracPrint(x3); printf("\n"); fracAdd(x3, fracMul(t1, x1, x1), fracMul(t2, x2, x2)); printf("x1*x1 + x2*x2 = "); fracPrint(x3); printf("\n"); fracFree(x1); fracFree(x2); fracFree(x3); fracFree(t1); fracFree(t2); return 0; }