Presentation is loading. Please wait.

Presentation is loading. Please wait.

関数とポインタ 値呼び出しと参照呼び出し swapのいろいろ 関数引数 数値積分

Similar presentations


Presentation on theme: "関数とポインタ 値呼び出しと参照呼び出し swapのいろいろ 関数引数 数値積分"— Presentation transcript:

1 関数とポインタ 値呼び出しと参照呼び出し swapのいろいろ 関数引数 数値積分
第11章 関数について 関数とポインタ 値呼び出しと参照呼び出し swapのいろいろ 関数引数 数値積分

2 10.7 関数とポインタ 関数名はポインタ 戻り値がポインタの関数 引数がポインタの関数 アドレスはプログラム領域
メモリ管理関数(malloc, calloc,...) 文字列処理関数(第13章、第15章) 配列や構造体を戻す関数 引数がポインタの関数 参照呼び出し(call by reference) scanfなど ⇔値呼び出し(call by value) 値をコピーして渡す

3 値呼び出しと参照呼び出し さて、 x と y の値がちゃんと交換されるのはどちらのプログラムだろうか。
#include <stdio.h> void swap(int x, int y) { int temp; temp=x; x=y; y=temp; printf("&x=%u:x=%d\n", &x,x); printf("&y=%u:y=%d\n", &y,y); } int main(void) int x=5, y=3; swap(x, y); printf("&x=%u:x=%d¥n", &x,x); printf("&y=%u:y=%d¥n", &y,y); return 0; #include <stdio.h> void swap(int *px, int *py) { int temp; temp=*px; *px=*py; *py=temp; printf("px=%u:*px=%d\n", px,*px); printf("py=%u:*py=%d\n", py,*py); } int main(void) int x=5, y=3; swap(&x, &y); printf("&x=%u:x=%d¥n", &x,x); printf("&y=%u:y=%d¥n", &y,y); return 0; 値呼び出し 参照呼び出し 3

4 値呼び出しと参照呼び出し Z:\nyumon2>swap_b &x=1245024:x=3 &y=1245028:y=5
Z:\nyumon2>swap_c px= :*px=3 py= :*py=5 &x= :x=3 &y= :y=5 swap x y 3 5 値の交換 5 3 値をコピー main x y 5 3 元のまま swap px py アドレスをコピー → ポインタ main x y 5 3 ポインタによる 値の交換 3 5

5 swapのいろいろ #include <stdio.h> void swap2(int *px, int *py) {
*px = *py - *px; *py -= *px; *px += *py; } int main(void) int x = 5, y = 3; swap2(&x, &y); printf("x = %d, y = %d\n", x, y); return 0; 変数 temp を使わない方法 *px += *py; *py = *px - *py; *px -= *py; または ポインタの交換はダメ 実数の場合、情報落ちが起きる swap2(&x, &x) はダメ

6 swapのいろいろ #include <stdio.h> void swap3(int *px, int *py) {
*px ^= *py; *py ^= *px; } int main(void) int x = 5, y = 3; swap3(&x, &y); printf("x = %d, y = %d\n", x, y); return 0; ビット演算子が使えるのは、 32 bit OSの場合、4バイト (32ビット)以下の整数型のみ swap3(&x, &x) はダメ

7 プログラム例 (数値積分) 定積分 x2 + y2 = 1 1 circle 0       1 y = x2 1 parabola 0       1

8 数値積分(台形公式) y y = f(x) f(a+2h) f(a+(n-1)h) f(a+h) f(b) f(a) h h h x
O a a+h a+2h a+(n-1)h b h h h x y y = f(x)

9 プログラム例 11.5.1(数値積分) 台形公式 integral sum ← 0 h ← (upper - lower) / n
sum ← sum + f(lower + i*h) 0.5*h*(2*sum + f(lower) + f(upper)) を戻す

10 積分ルーチンの仕様 関数名を内部で指定する場合 関数名を呼び出す側で指定する場合 関数1 積分ルーチン1 メイン関数 関数2 積分ルーチン2
専用ルーチン 積分ルーチン1 関数1 メイン関数 積分ルーチン2 関数2 関数3 積分ルーチン3 被積分関数ごとに作成 関数名を呼び出す側で指定する場合 汎用ルーチン 関数1 関数1 メイン関数 積分ルーチン 関数2 関数2 関数3 関数3 一つ作成すればOK

11 11.5 関数引数 関数名を渡すのに、関数へのポインタを使う プログラム例 11.5.1 より これまでに習ってきた例:実数 x,y が引数
double integral(double lower, double upper, int n, double (*f)(double)) { double h, sum; int i; sum = 0.0;   ・ } 変数なら   double f ポインタなら double *f となるところ… これまでに習ってきた例:実数 x,y が引数 単なるポインタと 区別するため、 関数へのポインタは カッコでくくる。 プログラム例 より double sum(double x, double y) { double z; z = x + y; return z; }

12 11.5 関数引数 プログラム例 11.5.1 #include <stdio.h>
#include <math.h> double circle(double); double parabola(double); double integral(double, double, int, double (*f)(double)); int main(void) { printf("circle__:%u, %f¥n",circle,integral(0.0,1.0,100,circle)); printf("parabola:%u, %f¥n",parabola,integral(0.0,1.0,100,parabola)); return 0; } double型関数へのポインタ を意味する 放物線 積分 1行目では 関数名 circle を, 2行目では 関数名 parabola を 実引数としている 次のスライドに続く 関数名もポインタ

13 プログラム例 11.5.1 関数 circle、関数 parabola と 関数 integral の関数定義部 f は仮引数
double integral(double lower, double upper, int n, double (*f)(double)) { double h, sum; int i; printf("f:%u, ",f); sum = 0.0; h = (upper - lower) / n; for (i = 1; i < n; i++) sum += f(lower + i * h); return 0.5 * h * (2.0 * sum + f(lower) + f(upper)); } double circle(double x) return sqrt(1.0 - x * x ); double parabola(double x) return x * x; f は仮引数 f(…)の部分では、main で呼ばれたときに 実引数となっている関数を呼び出す integral(…, circle) なら関数 circle を呼び、 integral(…, parabola) なら関数 parabola を呼ぶ

14 実行例 コマンドラインオプションで分割数 n を入力できるようにし、 小数点以下15桁表示するように改良せよ。
Z:\nyumon2>ex11_5_1 f: , circle__: , f: , palabora: , 関数へのポインタ(アドレス)が同じ コマンドラインオプションで分割数 n を入力できるようにし、 小数点以下15桁表示するように改良せよ。 Z:\nyumon2>ex11_5_1a f: , circle__: , f: , palabola: ,

15 本日のパズル 次のプログラムは何を出力するか
#include <stdio.h> #define PRINT(x,y) printf("%g\t%g\n",(double)x,(double)y) main() { double d=3.2, x; int i=2, y; x = (y=d/i)*2; PRINT(x,y); y = (x=d/i)*2; PRINT(x,y); x = d * (y =((int) )/d); PRINT(x,y); } 1 2 3


Download ppt "関数とポインタ 値呼び出しと参照呼び出し swapのいろいろ 関数引数 数値積分"

Similar presentations


Ads by Google