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

Slides:



Advertisements
Similar presentations
第 11 章 関数について 11.1 標準ライブラリ関数 11.2 関数呼び出しのオーバーヘッド 11.3 大域変数 11.4 プロトタイプ宣言 数学関数の自作.
Advertisements

C 言語講座 第 7 回 ポインター. メモリとアドレス(ポインターの前 に) コンピュータのメモリには 1 バイトずつ 0 番地、 1 番地、 2 番地・・・というように 住所が割り当てられている この住所をアドレスという。 メモリはデータをしまうもので それを引き出すためには メモリに番号(アドレス)を振っておけばよいな.
配列の宣言 配列要素の初期値 配列の上限 メモリ領域 多次元配列 配列の応用
情報基礎演習B 後半第5回 担当 岩村 TA 谷本君.
数理情報工学演習第一C プログラミング演習 (第3回 ) 2014/04/21
プログラミング論 数値積分
第13回構造体.
課題解説: 関数の引数にポインタを使って2数を入れ替える
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
16.3 関数と構造体 構造体ポインタ 地底探査ゲーム
プログラミング演習(2組) 第12回
情報処理Ⅱ 2005年12月9日(金).
C言語講座 第4回 ポインタ.
プログラミング言語論 第4回 手続きの引数機構 変数の有効範囲
構造体.
第4回放送授業.
プログラミング演習Ⅰ 課題2 10進数と2進数 2回目.
ちょっとした練習問題① 配列iroを['R', 'W', 'R', 'R', 'W' , 'W' , 'W']を宣言して、「W」のときの配列の番号をprintfで表示するようなプログラムを記述しなさい。
プログラミング言語論 第9回 Hoare論理の練習問題 手続きの引数機構 変数の有効範囲
関数と配列とポインタ 1次元配列 2次元配列 配列を使って結果を返す 演習問題
数値積分.
関数の定義.
第10回関数 Ⅱ (ローカル変数とスコープ).
プログラミング演習I 2003年5月7日(第4回) 木村巌.
プログラミング入門2 第8回 ポインタ 情報工学科 篠埜 功.
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
プログラミング 3 構造体(2).
プログラミング入門2 第11回 情報工学科 篠埜 功.
第13章 文字の取り扱い方 13.1 文字と文字型変数 13.2 文字列 13.3 文字型配列への文字列の代入
第13章 文字の取り扱い方 13.1 文字と文字型関数 13.2 文字列 13.3 文字型配列への文字列の代入
第9回関数Ⅰ (簡単な関数の定義と利用) 戻り値.
プログラミング入門2 第11回 情報工学科 篠埜 功.
第7回 プログラミングⅡ 第7回
復習 前回の関数のまとめ(1) 関数はmain()関数または他の関数から呼び出されて実行される.
アルゴリズムとデータ構造 補足資料5-1 「メモリとポインタ」
地域情報学 C言語プログラミング 第5回 ポインタ、関数、ファイル入出力 2017年11月17日
第11回 プログラミングⅡ 第11回
復習 2次元配列 4列 j = 0 j = 1 j = 2 j = 3 i = 0 i = 1 i = 2 3行
関数の再帰呼び出しとは ハノイの塔 リダイレクト レポート課題
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
プログラミング言語論 第5回 手続きの引数機構 変数の有効範囲
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
配列変数とポインタ 静的確保と動的確保 ポインタ配列 2次元配列 時間計測 第1回レポートの課題
メモリとメモリアドレス, ポインタ変数,関数へのポインタ渡し
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
プログラミング言語論 第六回 理工学部 情報システム工学科 新田直也.
構造体と共用体.
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
プログラミング入門2 第9回 ポインタ 情報工学科 篠埜 功.
復習 2次元配列 4列 j = 0 j = 1 j = 2 j = 3 i = 0 i = 1 i = 2 3行
ポインタとポインタを用いた関数定義.
第13章 文字の取り扱い方 13.1 文字と文字型変数 13.2 文字列 13.3 文字型配列への文字列の代入
情報基礎演習B 後半第2回 担当 岩村 TA 谷本君.
第13回 ポインタ 1 1.
11.1 標準ライブラリ関数 11.2 関数呼び出しのオーバーヘッド 11.3 大域変数 11.4 プロトタイプ宣言 11.5 関数引数
第5回 プログラミングⅡ 第5回
X64 函数呼び出し規約 長谷川啓
プログラミング演習II 2004年11月 2日(第3回) 理学部数学科・木村巌.
プログラミング入門2 第5回 配列 変数宣言、初期化について
値渡しと参照渡しについて.
第2章 数値の入力と変数 scanfと変数をやります.
計算技術研究会 第5回 C言語勉強会 関数(function)を使う
プログラミング演習I 補講用課題
第1章 文字の表示と計算 printfと演算子をやります 第1章 文字の表示と計算.
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
プログラミング 3 ポインタ(1).
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
Presentation transcript:

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

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

値呼び出しと参照呼び出し さて、 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

値呼び出しと参照呼び出し Z:\nyumon2>swap_b &x=1245024:x=3 &y=1245028:y=5 Z:\nyumon2>swap_c px=1245032:*px=3 py=1245036:*py=5 &x=1245032:x=3 &y=1245036:y=5 swap 1245024 x 1245028 y 3 5 値の交換 5 3 値をコピー main 1245032 x 1245036 y 5 3 元のまま swap 1245024 px 1245028 py 1245032 1245036 アドレスをコピー → ポインタ main 1245032 x 1245036 y 5 3 ポインタによる 値の交換 3 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) はダメ

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) はダメ

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

数値積分(台形公式) 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)

プログラム例 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)) を戻す

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

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 が引数 単なるポインタと 区別するため、 関数へのポインタは カッコでくくる。 プログラム例 10.1.3 より double sum(double x, double y) { double z; z = x + y; return z; }

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 を 実引数としている 次のスライドに続く 関数名もポインタ

プログラム例 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 を呼ぶ

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

本日のパズル 次のプログラムは何を出力するか #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)2.9+1.1)/d); PRINT(x,y); } 1 2 3