• 検索結果がありません。

Microsoft PowerPoint - 09.pptx

N/A
N/A
Protected

Academic year: 2021

シェア "Microsoft PowerPoint - 09.pptx"

Copied!
30
0
0

読み込み中.... (全文を見る)

全文

(1)

情報処理Ⅱ

第9回

(2)

2

関数とは・なぜ関数

関数の分類

 自作関数: 自分で定義する.「ユーザ関数」「ユーザ定義関 数」などともいう.⇒ 本日のテーマ  ライブラリ関数: 出来合いのもの.printfなど. 

なぜ関数を定義するのか?

 処理を共通化(一般化)する  プログラムの見通しをよくする • 機能分割(モジュール化,再利用) • 責任(あるいは不具合の発生源)の最小化  main関数がないとプログラムは動かない

(3)

仮引数と実引数

関数定義の例

 int min(int x, int y) {...}

関数呼び出しの例

 printf("min: %d¥n", min(x, y));

仮引数と実引数の区別

 関数定義のxとyは仮引数.変数であり,それぞれ型名を書く

• 「int min(int x, y)」は間違い

 関数呼び出しのxとyは実引数.任意の式でよい  仮引数に,実引数の式の評価値を代入してから,関数の処理 が始まる  仮引数と実引数が同じ変数名であっても,有効範囲が異なる ため,別オブジェクトとなる 3

(4)

4

引数の授受

Cの関数呼び出しでは必ず

値渡し

(call by value)になる.

 値渡し: 実引数のコピーが仮引数に格納される.その後,仮 引数の値を変更しても,実引数の値には影響しない. 

参照渡し

(call by reference)をしたければ,ポインタ値

を引数とすればよい.

 参照渡し: 仮引数の値を変更すれば,実引数の値もそれに変 わる.Cではこの意味での参照渡しをすることができないが,ポ インタ値を渡すことで,その参照先の値を変えることができる. アドレス渡しともいう.

(5)

5

2つの値を交換する関数

値渡し ⇒ 失敗

 引数は関数内の仮引数にコピーされる.  関数内の仮引数の中で,値を交換しても,関数の外のオブジェ クトは変更されない. 

参照渡し ⇒ 成功

 関数の仮引数は,指し示す先を持つ.  「*ポインタ変数 = 値」とすることで,ポインタ変数が指し示す (関数の外の)オブジェクトに値を代入する. swapint.c

(6)

6

値渡しで失敗する理由(1)

コード(抜粋)

 void swapint_bad(int x, int y) 

{ int tmp; tmp = x; x = y; y = tmp; }  x = 1, y = ‐1; swapint_bad(x, y); swapint_bad main y = -1 x = 1

(7)

7

値渡しで失敗する理由(2)

コード(抜粋)

 void swapint_bad(int x, int y) 

{ int tmp; tmp = x; x = y; y = tmp; }  x = 1, y = ‐1; swapint_bad(x, y); swapint_bad y = -1 x = 1 main y = -1 x = 1

(8)

8

値渡しで失敗する理由(3)

コード(抜粋)

 void swapint_bad(int x, int y) 

{ int tmp; tmp = x; x = y; y = tmp; }  x = 1, y = ‐1; swapint_bad(x, y); swapint_bad y = -1 x = 1 main y = -1 x = 1 tmp

(9)

9

値渡しで失敗する理由(4)

コード(抜粋)

 void swapint_bad(int x, int y) 

{ int tmp; tmp = x; x = y; y = tmp; }  x = 1, y = ‐1; swapint_bad(x, y); swapint_bad y = -1 x = 1 main y = -1 x = 1 tmp tmp=1

(10)

10

値渡しで失敗する理由(5)

コード(抜粋)

 void swapint_bad(int x, int y) 

{ int tmp; tmp = x; x = y; y = tmp; }  x = 1, y = ‐1; swapint_bad(x, y); swapint_bad y = -1 x = 1 main y = -1 x = 1 tmp tmp=1 x = -1

(11)

11

値渡しで失敗する理由(6)

コード(抜粋)

 void swapint_bad(int x, int y) 

{ int tmp; tmp = x; x = y; y = tmp; }  x = 1, y = ‐1; swapint_bad(x, y); swapint_bad y = -1 x = 1 main y = -1 x = 1 tmp tmp=1 x = -1 y = 1

(12)

12

値渡しで失敗する理由(7)

コード(抜粋)

 void swapint_bad(int x, int y) 

{ int tmp; tmp = x; x = y; y = tmp; }  x = 1, y = ‐1; swapint_bad(x, y); swapint_bad y = -1 x = 1 main y = -1 x = 1 tmp tmp=1 x = -1 y = 1

(13)

13

参照渡しで成功する理由(1)

コード(抜粋)

 void swapint_good(int *px, int *py)  { int tmp; tmp = *px; *px = *py; *py = tmp; }  x = 1, y = ‐1; swapint_good(&x, &y); swapint_good main y = -1 x = 1

(14)

14

参照渡しで成功する理由(2)

コード(抜粋)

 void swapint_good(int *px, int *py)  { int tmp; tmp = *px; *px = *py; *py = tmp; }  x = 1, y = ‐1; swapint_good(&x, &y); swapint_good main y = -1 x = 1 py px

(15)

15

参照渡しで成功する理由(3)

コード(抜粋)

 void swapint_good(int *px, int *py)  { int tmp; tmp = *px; *px = *py; *py = tmp; }  x = 1, y = ‐1; swapint_good(&x, &y); swapint_good main y = -1 x = 1 tmp py px

(16)

16

参照渡しで成功する理由(4)

コード(抜粋)

 void swapint_good(int *px, int *py)  { int tmp; tmp = *px; *px = *py; *py = tmp; }  x = 1, y = ‐1; swapint_good(&x, &y); swapint_good main y = -1 x = 1 tmp tmp=1 py px

(17)

17

参照渡しで成功する理由(5)

コード(抜粋)

 void swapint_good(int *px, int *py)  { int tmp; tmp = *px; *px = *py; *py = tmp; }  x = 1, y = ‐1; swapint_good(&x, &y); swapint_good main y = -1 x = 1 tmp tmp=1 x = -1 py px

(18)

18

参照渡しで成功する理由(6)

コード(抜粋)

 void swapint_good(int *px, int *py)  { int tmp; tmp = *px; *px = *py; *py = tmp; }  x = 1, y = ‐1; swapint_good(&x, &y); swapint_good main y = -1 x = 1 tmp tmp=1 x = -1 y = 1 py px

(19)

19

参照渡しで成功する理由(7)

コード(抜粋)

 void swapint_good(int *px, int *py)  { int tmp; tmp = *px; *px = *py; *py = tmp; }  x = 1, y = ‐1; swapint_good(&x, &y); swapint_good main y = -1 x = 1 tmp tmp=1 x = -1 y = 1 py px

(20)

20

関数の中の配列変数(1)

関数の中で配列変数を定義すれば,関数処理の中で確保さ

れ,関数処理が終わると破棄されるような配列が作られる.

void print_message(void) { char message[] = "Wakayama"; printf("%s¥n", message); }

message

print_message

(21)

21

関数の中の配列変数(2)

関数の仮引数に配列変数を書けば,その配列と型が適合す

るポインタ変数になる.

void print_message(char message[]) { printf("%s¥n", message); }  要素数(多次元配列の場合は左端のみ)は無視される. 要素数なしでもよい.

message

print_message

'W'

'a'

'k'

'a'

'y'

'a'

'm''a'

'¥0' 不完全型

(22)

多項式の計算

仕様

 多項式関数 f(x) = cnxn + cn‐1xn‐1 + … + c1x + c0 と実数aが与えられたときに,f(a)を計算する. 

考え方

 係数 c0, c1, c2, … cn を,配列変数で保持する. • ci は,xのi次の係数

 f(a) = (…(cn * a) + cn‐1) * a + …) + c0

により求め(ホーナー法),乗算の回数を減らす. • v0 = cn

• v1 = v0 * a + cn‐1

• v2 = v1 * a + cn‐2 = cn*a*a + cn‐1*a + cn‐2 • vi = vi‐1 * a + cn‐i

22

(23)

多項式の計算を行う関数

コード(抜粋)

 double calc(double f[], int size, double x) { double val; int i; val = f[size ‐ 1];

for(i = size ‐ 2; i >= 0; i‐‐){ val = val * x + f[i];

} return val; } 

関数定義の効果:異なる次数の多項式でも,一つの(Cの)関

数calcにより,値を求められる.

23 係数の配列(の先頭を 指し示すポインタ変数) f の配列の要素数 (xの次数 + 1) f(x) を求める ためのxの値 v ← cn v ← v*x  + cn‐i v = f(x) = cnxn + c n‐1xn‐1 + …  + c1x + c0 polynomial.c

(24)

24

「関数と変数」で学ぶこと

目的

 関数を自分で定義し,変数の利用方法・範囲を明示的に制限 することで,適切な機能分割(モジュール化,再利用)を図る. 

してはいけないこと

 main関数のみで100行以上のプログラム  グローバル変数を駆使するプログラム プログラムを 読みやすくする ⇒ 保守性向上

(25)

25

変数

(Variable)・識別子・オブジェクト

識別子(Identifier): 変数名,関数名,型定義名などの

「名前」

識別子とオブジェクト(Object)の違い

 識別子は,プログラムファイル(静的)で記述される「ラベル」  オブジェクトは,プログラム実行中(動的)に生成される「実体」  同一の識別子に対して複数のオブジェクトが生成されることも ある.

(26)

26

識別子の宣言に関するルール

グローバルに同一の識別子を複数宣言できない.

一つのブロック内に,同一の識別子を複数宣言できない.

関数はブロック内で定義できない.必ずグローバル区間での

定義となる.

 GCC(演習室のコンパイラ)では,関数の中に関数を定義できる が,使用しないこと! 

ブロック内に変数を定義するときは,それより外にある同一

の識別子と重複してもよい.

 ただし,外にある同一の識別子は参照できない.  モジュール化に関して有用なルール.

(27)

27

2つの重要な記憶域クラス

静的記憶域期間 (

静的変数

,static変数)

 staticを指定した変数と,グローバル変数が該当する.  プログラムの実行に先立ち,オブジェクトが生成され,初期値が設定 される.プログラム終了まで破棄されない.  初期値を指定しないオブジェクトには 0 が代入される.  初期値は,コンパイル時に計算可能な定数式でなければならない. 

自動記憶域期間 (

自動変数

,auto変数)

 autoを指定した変数,staticやexternの指定なくブロック内で定義 した変数と,関数の仮引数が該当する.  宣言文を実行するたびに,オブジェクトが生成され,初期値があれば 毎回初期化される.ブロックを終えると,破棄される.  初期値を指定しないオブジェクトの初期値は不定.  初期値は任意の計算式でよい.

(28)

28

有効範囲と記憶域クラス

ここで問題

(小テストではありません)  グローバルな静的変数は,宣言《 できる ∥ できない 》.  グローバルな自動変数は,宣言《 できる ∥ できない 》.  ローカルな静的変数は,宣言《 できる ∥ できない 》.  ローカルな自動変数は,宣言《 できる ∥ できない 》. 

ローカルな静的変数の用途

 ブロック内で情報を保存しておき,あとで利用する.  動的に確保することなく,配列領域を戻り値とする.  自動変数では扱いきれない大容量オブジェクト(100万個の int配列など)を取り扱う.

(29)

29

有効範囲と生存期間

破棄されるまでは,ブロックの外からでも(ポインタなどで間

接的に)オブジェクトの参照や値の書き換えができる.

⇒ ポインタによる参照渡しが可能となる.

関数内の自動変数に対応するオブジェクトは,関数処理が

行われるたびに生成される.

⇒ 「再帰呼び出しをする関数」が構成できる.

'W'

'a'

'k'

'a'

'y'

'a'

'm''a'

'¥0'

message

何らかの関数の中

wakayama

message[0] = 'w'; としてよい

(30)

年末年始の授業予定

12月25日(木):第10回,レポート課題提示

1月8日(木):第11回

1月19日(月):第12回

1月26日からの週には3回授業があり,そのうち1回はA601

で実施します.

30

参照

関連したドキュメント

READ UNCOMMITTED 発生する 発生する 発生する 発生する 指定してもREAD COMMITEDで動作 READ COMMITTED 発生しない 発生する 発生する 発生する デフォルト.

世界的流行である以上、何をもって感染終息と判断するのか、現時点では予測がつかないと思われます。時限的、特例的措置とされても、かなりの長期間にわたり

ダウンロードしたファイルを 解凍して自動作成ツール (StartPro2018.exe) を起動します。.

次亜塩素酸ナトリウムは蓋を しないと揮発されて濃度が変 化することや、周囲への曝露 問題が生じます。作成濃度も

Windows Mobile デバイスセンターまたは ActiveSync をインストールすることで、パソコ ンと FC-250 との間でパートナーシップの設定や、Microsoft Outlook

○○でございます。私どもはもともと工場協会という形で活動していたのですけれども、要

口文字」は患者さんと介護者以外に道具など不要。家で も外 出先でもどんなときでも会話をするようにコミュニケー ションを

里親委託…里親とは、さまざまな事情で家庭で育てられない子どもを、自分の家庭に