情報処理Ⅱ
情報処理Ⅱ
第8回
2009年12月7日(月)
2009年12月7日(月)
本日学ぶこと
本日学ぶこと
関数と変数
目的
目的
関数を自分で定義し,変数の利用方法・範囲を明示的に制限 することで 適切な機能分割(モジュール化 再利用)を図る することで,適切な機能分割(モジュ ル化,再利用)を図る. してはいけないこと
i 関数のみで100行以上のプログラム プログラムを 読みやすくする main関数のみで100行以上のプログラム グローバル変数を駆使するプログラム問題
読みやすくする ⇒ 保守性保守性向上 問題
多項式関数 f(x) = c0 + c1x + c2x2 + … + cnxn 実数 が与 れた き f を計算 きる と実数aが与えられたときに,f(a)を計算できる? • 次数nの異なる様々な関数に対して,求められる? 2 入p.109関数
(F
ti )
関数
(Function)
関数の分類
自作関数: 自分で定義する ⇒ 本日のテーマ 自作関数: 自分で定義する.⇒ 本日のテ マ ライブラリ関数: 出来合いのもの.printfなど. なぜ関数を定義するのか?
なぜ関数を定義するのか?
処理を共通化(一般化)する プ グラムの見通しをよくする プログラムの見通しをよくする main関数がないとプログラムは動かない 3 入pp.274-275 リp.346関数定義の方法
関数定義の方法
構文
:
型名
型名 関数名
関数名
(
(引数並び
引数並び
) {
) {文
文
...}
...}
型名は 関数の戻り値の型 値を返さないときは voidvoidと書く 型名は,関数の戻り値の型.値を返さないときは,voidvoidと書く. 引数並びは,「型名 変数名」をカンマで区切ったもの. 引数がないときは voidvoidと書く 引数がないときは,voidvoidと書く. 例: double double myatofmyatof(const char *str0) {…}(const char *str0) {…} 例: void procedure(void procedure(intint xx intint y) { }y) { }
例: void procedure(void procedure(intint x, x, intint y) {…}y) {…}
一括の変数宣言と異なり括の変数宣言と異なり, このintは省略できない.
4
id型
void型
void
void
は「何もない」や「無効な値」を表す型名
×× void x;void x; ×× void x;void x; ○○ void *x;void *x; 用途
用途
関数が引数や戻り値を持たないことを明示するとき id ii (i )• void exitexit(int status);
•
• void procedure(void);void procedure(void); プログラムを終了するライブラリ関数.通常,exit(0);exit(0); もしくは exit(1);exit(1); のいず 任意のポインタ型を表現するとき • • void *p;void *p; もしくは exit(1);exit(1); のいず れかで呼び出す.
• void *mallocmalloc(size_t size);
5
関数の呼び出し
関数の呼び出し
関数定義の例:
double f(double x) {return x+1;}
double f(double x) {return x+1;}
double f(double x) {return x+1;}
double f(double x) {return x+1;}
関数呼び出しの例:
b=f(a);
b=f(a);
x を関数 f の仮引数仮引数(parameter) 変数aの値を引数として, 関数fを呼び出し,その戻 x を関数 f の仮引数仮引数(parameter), a を関数 f の実引数実引数(argument) という.これらを区別する必要のないときは,ともに引数引数という. 関数 を呼び出し,その戻 り値を,変数bに代入する. という.これらを区別する必要のないときは,ともに引数引数という. • 仮引数の宣言には型名も書く.実引数には書かない. x = a; の代入を行ってから 関数本文の処理に入る 関数 x = a; の代入を行ってから,関数本文の処理に入る.関数 の処理が終われば,変数 x (のオブジェクト)は消滅する. x = f(x); と書いてもよい このとき 仮引数の x と 実 x = f(x); と書いてもよい.このとき,仮引数の x と,実 引数の x (あらかじめ定義しておく)は,別のオブジェクトであ る. 6 入pp.277-278 リpp.347-348t
return
関数処理中に
return
return 値
値
;
;
があれば,そこで関数の処理
を終え,値を
戻り値
戻り値
(return value)とする.
を終え,値を
戻り値
戻り値
(return value)とする.
値の前後にカッコは不要. 戻り値の型がvoidなら return;return; と書ける 戻り値の型がvoidなら, return;return; と書ける.
戻り値の型がvoid以外なら,必ずreturn 値;で処理を終え
るように書く るように書く.
7
引数の授受
引数の授受
Cの関数呼び出しでは必ず
値渡し
値渡し
(call by value)にな
る.
る.
値渡し: 実引数のコピーコピーが仮引数に格納される.その後,仮 引数の値を変更しても,実引数の値には影響しない. 引数の値を変更しても,実引数の値には影響しない. 参照渡し
参照渡し
(call by reference)をしたければ,ポインタ
値を引数とすればよい
値を引数とすればよい.
参照渡し: 仮引数の値を変更すれば,実引数の値もそれに変 わる Cではこの意味での参照渡しをすることができないが ポ わる.Cではこの意味での参照渡しをすることができないが,ポ インタ値を渡すことで,その参照先の値を変える参照先の値を変えることができる. アドレス渡しともいう. 8 入p.277, p.285 リpp.347-348二つの値を交換する関数
二つの値を交換する関数
値渡し ⇒ 失敗
引数は関数内の仮引数にコピーされる 引数は関数内の仮引数にコピ される. 関数内の仮引数の中で,値を交換しても,関数の外のオブジェ クトは変更されない クトは変更されない. 参照渡し ⇒ 成功
関数の仮引数は 指し示す先を持つ 関数の仮引数は,指し示す先を持つ. 「*ポインタ変数 = 値」とすることで,ポインタ変数が指し示す (関数の外の)オブジェクトに値を代入する (関数の外の)オブジェクトに値を代入する. 9 swapint.c値渡しで失敗する理由(1)
値渡しで失敗する理由(1)
コード(抜粋)
voidvoid swapint badswapint bad((intint xx intint y)y)
void void swapint_badswapint_bad((intint x, x, intint y) y)
{ {
int
int tmptmp;pp;;; swapint bad
tmp tmp = x;= x; p _ x = y; x = y; y = y = tmptmp;; } } } } x x = 1, y = = 1, y = --1;1; swapint bad
swapint bad(x(x y);y); x = 1 y = -1
swapint_bad
swapint_bad(x, y);(x, y);
main y 1 x 1 10 main 入p.230
値渡しで失敗する理由(2)
値渡しで失敗する理由(2)
コード(抜粋)
voidvoid swapint badswapint bad((intint xx intint y)y)
void void swapint_badswapint_bad((intint x, x, intint y) y)
{ {
int
int tmptmp;pp;;; swapint bad
tmp tmp = x;= x; p _ y = -1 x = 1 x = y; x = y; y = y = tmptmp;; } } } } x x = 1, y = = 1, y = --1;1; swapint bad
swapint bad(x(x y);y); x = 1 y = -1
swapint_bad
swapint_bad(x, y);(x, y);
main y 1 x 1 11 main 入p.230
値渡しで失敗する理由(3)
値渡しで失敗する理由(3)
コード(抜粋)
voidvoid swapint badswapint bad((intint xx intint y)y)
void void swapint_badswapint_bad((intint x, x, intint y) y)
{ {
int
int tmptmp;pp;;; swapint bad
tmp tmp = x;= x; p _ y = -1 x = 1 x = y; x = y; y = y = tmptmp;; } } tmp } } x x = 1, y = = 1, y = --1;1; swapint bad
swapint bad(x(x y);y); x = 1 y = -1
swapint_bad
swapint_bad(x, y);(x, y);
main y 1 x 1 12 main 入p.230
値渡しで失敗する理由(4)
値渡しで失敗する理由(4)
コード(抜粋)
voidvoid swapint badswapint bad((intint xx intint y)y)
void void swapint_badswapint_bad((intint x, x, intint y) y)
{ {
int
int tmptmp;pp;;; swapint bad
tmp tmp = x;= x; p _ y = -1 x = 1 x = y; x = y; y = y = tmptmp;; } } tmp=1tmp } } x x = 1, y = = 1, y = --1;1; swapint bad
swapint bad(x(x y);y); x = 1 y = -1
swapint_bad
swapint_bad(x, y);(x, y);
main y 1 x 1 13 main 入p.230
値渡しで失敗する理由(5)
値渡しで失敗する理由(5)
コード(抜粋)
voidvoid swapint badswapint bad((intint xx intint y)y)
void void swapint_badswapint_bad((intint x, x, intint y) y)
{ {
int
int tmptmp;pp;;; swapint bad
tmp tmp = x;= x; p _ y = -1 x = 1 x = -1 x = y; x = y; y = y = tmptmp;; } } tmp=1tmp } } x x = 1, y = = 1, y = --1;1; swapint bad
swapint bad(x(x y);y); x = 1 y = -1
swapint_bad
swapint_bad(x, y);(x, y);
main y 1 x 1 14 main 入p.230
値渡しで失敗する理由(6)
値渡しで失敗する理由(6)
コード(抜粋)
voidvoid swapint badswapint bad((intint xx intint y)y)
void void swapint_badswapint_bad((intint x, x, intint y) y)
{ {
int
int tmptmp;pp;;; swapint bad
tmp tmp = x;= x; p _ y = -1 x = 1 x = -1 y = 1 x = y; x = y; y = y = tmptmp;; } } tmp=1tmp } } x x = 1, y = = 1, y = --1;1; swapint bad
swapint bad(x(x y);y); x = 1 y = -1
swapint_bad
swapint_bad(x, y);(x, y);
main y 1 x 1 15 main 入p.230
値渡しで失敗する理由(7)
値渡しで失敗する理由(7)
コード(抜粋)
voidvoid swapint badswapint bad((intint xx intint y)y)
void void swapint_badswapint_bad((intint x, x, intint y) y)
{ {
int
int tmptmp;pp;;; swapint bad
tmp tmp = x;= x; p _ y = -1 x = 1 x = -1 y = 1 x = y; x = y; y = y = tmptmp;; } } tmp=1tmp } } x x = 1, y = = 1, y = --1;1; swapint bad
swapint bad(x(x y);y); x = 1 y = -1
swapint_bad
swapint_bad(x, y);(x, y);
main y 1 x 1 16 main 入p.230
参照渡しで成功する理由(1)
参照渡しで成功する理由(1)
コード(抜粋)
voidvoid swapint goodswapint good((intint **pxpx intint **pypy))
void void swapint_goodswapint_good((intint pxpx, , intint pypy) )
{ {
int
int tmptmp;pp;;; swapint good
tmp tmp = *= *pxpx;; swapint_good * *pxpx = *= *pypy;; * *pypy = = tmptmp;; } } } } x x = 1, y = = 1, y = --1;1; swapint good
swapint good(&x(&x &y);&y); x = 1 y = -1 swapint_good
swapint_good(&x, &y);(&x, &y);
main y 1 x 1 17 main リp.356
参照渡しで成功する理由(2)
参照渡しで成功する理由(2)
コード(抜粋)
voidvoid swapint goodswapint good((intint **pxpx intint **pypy))
void void swapint_goodswapint_good((intint pxpx, , intint pypy) )
{ {
int
int tmptmp;pp;;; swapint good
tmp tmp = *= *pxpx;; swapint_good py px * *pxpx = *= *pypy;; * *pypy = = tmptmp;; } } } } x x = 1, y = = 1, y = --1;1; swapint good
swapint good(&x(&x &y);&y); x = 1 y = -1 swapint_good
swapint_good(&x, &y);(&x, &y);
main y 1 x 1 18 main リp.356
参照渡しで成功する理由(3)
参照渡しで成功する理由(3)
コード(抜粋)
voidvoid swapint goodswapint good((intint **pxpx intint **pypy))
void void swapint_goodswapint_good((intint pxpx, , intint pypy) )
{ {
int
int tmptmp;pp;;; swapint good
tmp tmp = *= *pxpx;; swapint_good py px * *pxpx = *= *pypy;; * *pypy = = tmptmp;; } } tmp } } x x = 1, y = = 1, y = --1;1; swapint good
swapint good(&x(&x &y);&y); x = 1 y = -1 swapint_good
swapint_good(&x, &y);(&x, &y);
main y 1 x 1 19 main リp.356
参照渡しで成功する理由(4)
参照渡しで成功する理由(4)
コード(抜粋)
voidvoid swapint goodswapint good((intint **pxpx intint **pypy))
void void swapint_goodswapint_good((intint pxpx, , intint pypy) )
{ {
int
int tmptmp;pp;;; swapint good
tmp tmp = *= *pxpx;; swapint_good py px * *pxpx = *= *pypy;; * *pypy = = tmptmp;; } } tmp=1tmp } } x x = 1, y = = 1, y = --1;1; swapint good
swapint good(&x(&x &y);&y); x = 1 y = -1 swapint_good
swapint_good(&x, &y);(&x, &y);
main y 1 x 1 20 main リp.356
参照渡しで成功する理由(5)
参照渡しで成功する理由(5)
コード(抜粋)
voidvoid swapint goodswapint good((intint **pxpx intint **pypy))
void void swapint_goodswapint_good((intint pxpx, , intint pypy) )
{ {
int
int tmptmp;pp;;; swapint good
tmp tmp = *= *pxpx;; swapint_good py px * *pxpx = *= *pypy;; * *pypy = = tmptmp;; } } tmp=1tmp } } x x = 1, y = = 1, y = --1;1; swapint good
swapint good(&x(&x &y);&y); x = -1x = 1 y = -1 swapint_good
swapint_good(&x, &y);(&x, &y);
main y 1 x 1 x 1 21 main リp.356
参照渡しで成功する理由(6)
参照渡しで成功する理由(6)
コード(抜粋)
voidvoid swapint goodswapint good((intint **pxpx intint **pypy))
void void swapint_goodswapint_good((intint pxpx, , intint pypy) )
{ {
int
int tmptmp;pp;;; swapint good
tmp tmp = *= *pxpx;; swapint_good py px * *pxpx = *= *pypy;; * *pypy = = tmptmp;; } } tmp=1tmp } } x x = 1, y = = 1, y = --1;1; swapint good
swapint good(&x(&x &y);&y); x = -1x = 1 y = -1y = 1 swapint_good
swapint_good(&x, &y);(&x, &y);
main y 1 x 1 x 1 y 1 22 main リp.356
参照渡しで成功する理由(7)
参照渡しで成功する理由(7)
コード(抜粋)
voidvoid swapint goodswapint good((intint **pxpx intint **pypy))
void void swapint_goodswapint_good((intint pxpx, , intint pypy) )
{ {
int
int tmptmp;pp;;; swapint good
tmp tmp = *= *pxpx;; swapint_good py px * *pxpx = *= *pypy;; * *pypy = = tmptmp;; } } tmp=1tmp } } x x = 1, y = = 1, y = --1;1; swapint good
swapint good(&x(&x &y);&y); x = -1x = 1 y = -1y = 1 swapint_good
swapint_good(&x, &y);(&x, &y);
main y 1 x 1 x 1 y 1 23 main リp.356
i 関数の型
main関数の型
main関数の(戻り値の)型は,int とする.
void main とする本も多いが 規格上適切ではない void main とする本も多いが,規格上適切ではない. 正常終了は
return 0;
return 0;
と書き,
異常終了は
return 1;
return 1;
と書くのが一般的
異常終了は
return 1;
return 1;
と書くのが一般的.
main関数が返す値,およびexit関数の引数は,
終了ステ タス
(exit status)と呼ばれる
終了ステータス
(exit status)と呼ばれる.
Linuxなら,コマンド実行後,「echo $?」を実行することで その値を確認できる その値を確認できる. 「コンパイルが成功したときに限り,ファイルを実行する」が 一つのコマンドで書ける 一つのコマンドで書ける 24 リpp.359-362関数定義の順番
関数定義の順番
呼び出す関数は,呼び出す前に(プログラムファイルの上の
ほうで)宣言されていなければならない.
ほうで)宣言されていなければならない.
宣言や定義がない場合は,intint 関数名関数名();(); とみなして呼び 出しを試みる. 出しを試みる. 対策
呼び出す順序に注意して関数を並べる 呼び出す順序に注意して関数を並べる. 関数プロトタイプを使用する. 25関数プロトタイプ
「関数原型」関数
トタイ
(Function prototype)
「関数原型」 ともいう 構文
:
型名
型名 関数名
関数名
(
(引数の型の並び
引数の型の並び
);
);
「引数の型の並び」は 「引数(型と変数)の並び」でもよい こ セミコロンを忘れずに 「引数の型の並び」は,「引数(型と変数)の並び」でもよい.こ のとき変数名は無視される. 一般に 各関数の定義より前(上)に記述する 般に,各関数の定義より前(上)に記述する. 例: intint swapint_goodswapint_good((intint **, , intint *);*);
関数プロトタイプを用いることで
関数プロトタイプを用いることで,
関数定義の順番を気にすることなく順番を気にすることなくプログラムを記述できる. 関数の入出力が明確になる 関数の入出力が明確になる. 26 入pp.278-279 リpp.350-351変数
(V i bl ) 識別子 オブジ クト
変数
(Variable)・識別子・オブジェクト
識別子
(Identifier): 変数名,関数名,型定義名など
の「名前」
の 名前」
識別子とオブジェクト
(Object)の違い
識別子は プログラムファイル(静的)で記述される「ラベル」 識別子は,プログラムファイル(静的)で記述される「ラベル」 オブジェクトは,プログラム実行中(動的)に生成される「実体」 同 の識別子に対して複数のオブジ クトが生成されることも 同一の識別子に対して複数のオブジェクトが生成されることも ある.宣言
宣言
により 変数ならそのオブジ クト 関数ならその実行
宣言
宣言
により,変数ならそのオブジェクト,関数ならその実行
コードが,記憶域(メモリ)上に割り当てられるとき,
その宣言を特に
定義
定義
という
その宣言を特に
定義
定義
という.
関数プロトタイプや,externを用いた変数や関数の宣言, 構造体などの独自型定義は この意味で定義ではない 27 構造体などの独自型定義は,この意味で定義ではない. 入p.223 リp.37, pp.102-103変数を宣言 定義する際の注意点
変数を宣言・定義する際の注意点
型は何か?
グローバルかローカルか?
グローバルかローカルか?
auto(自動)かstatic(静的)かextern(外部)か?
28 リpp.104-106グロ バル変数とロ カル変数
グローバル変数とローカル変数
各変数は,定義された位置によって,有効範囲
(scope)を
持つ.
持つ.
グローバル変数 • あらゆるブロックの外で定義された変数 • あらゆるブロックの外で定義された変数. • 有効範囲はファイル末尾まで. ロ カル変数 「ブロックの中」とは, { と }で ローカル変数 • ブロックの中で定義された変数. 有効範囲はブロ ク終了まで { と }で 挟まれた領域のこと • 有効範囲はブロック終了まで. グ バ l b l 大域的 あらゆるブ クの外 関数の仮引数も ローカル変数 グローバル - global - 大域的 - あらゆるブロックの外 ローカル - local - 局所的 - あるブロックの中 29 入pp.280-281 リpp.111-114識別子の宣言に関するル ル
識別子の宣言に関するルール
グローバルに同一の識別子を複数宣言できない.
一つのブロック内に 同一の識別子を複数宣言できない
つのブロック内に,同
の識別子を複数宣言できない.
関数はブロック内で定義できない.必ずグローバル区間での
定義となる
定義となる.
GCC(演習室のコンパイラ)では,関数の中に関数を定義できる が 使用しないこと! が,使用しないこと! ブロック内に変数を定義するときは,それより外にある同一
の識別子と重複してもよい
の識別子と重複してもよい.
ただし,外にある同一の識別子は参照できない. ジ 化 関 有 な モジュール化に関して有用なルール. 30 リp.114, p.225型の属性
型の属性
記憶域クラス
extern static auto register extern, static, auto, register
型修飾子
const volatile
const, volatile
例
:
extern void function1(const char *);
extern void function1(const char *);
i t
(
id) { t ti
i t
0
}
i t
(
id) { t ti
i t
0
}
int x(void) {static int c=0; ...}
int x(void) {static int c=0; ...}
31
記憶域クラス(1)
記憶域クラス(1)
auto
auto
: そのオブジェクトの生存期間は自動記憶域期間で
ある.
ある.
積極的にautoを書くことはない. static
static
: そのオブジェクトの生存期間は静的記憶域期間
static
static
: そのオブジェクトの生存期間は静的記憶域期間
である.
必要なときに使う 必要なときに使う. extern
extern
: 他の場所で宣言された識別子を使用する.
分割 パイ 不可欠 プログラムが複数のソースファイルで 構成されることがある.大規模プログ ラミングでは当たり前だが,本授業で 分割コンパイルで不可欠. externとstaticは,関数に 対しても指定できる ラミングでは当たり前だが,本授業では実例を出さない. 対しても指定できる. 32 リp.107記憶域クラス(2)
記憶域クラス(2)
静的記憶域期間 (
静的変数
静的変数
,
static変数)
staticを指定した変数と グローバル変数が該当する staticを指定した変数と,グロ バル変数が該当する. プログラムの実行に先立ち,オブジェクトが生成され,初期値が設定 される.プログラム終了まで破棄されない. 初期値を指定しないオブジェクトには 0 が代入される. 初期値は,コンパイル時に計算可能な定数式でなければならない. 自動記憶域期間 (
自動変数
自動変数
,
auto変数)
autoを指定した変数,staticやexternの指定なくブロック内で定 義した変数と,関数の仮引数が該当する. 宣言文を実行するたびに,オブジェクトが生成され,初期値があれば 毎回初期化される ブ クを終えると 破棄される 毎回初期化される.ブロックを終えると,破棄される. 初期値を指定しないオブジェクトの初期値は不定. 初期値は任意の計算式でよい 33 初期値は任意の計算式でよい. 入pp.226-227 リp.110, pp.115-120有効範囲?記憶域クラス?
有効範囲?記憶域クラス?
ここで問題
(小テストではありません) グローバルな静的変数は 定義《 できる ∥ できない 》 グロ バルな静的変数は,定義《 できる ∥ できない 》. グローバルな自動変数は,定義《 できる ∥ できない 》. ロ カルな静的変数は 定義《 できる ∥ できない 》 ローカルな静的変数は,定義《 できる ∥ できない 》. ローカルな自動変数は,定義《 できる ∥ できない 》. ローカルな静的変数の用途
ブロック内で情報を保存しておき,あとで利用する. 動的に確保することなく,配列領域を戻り値とする. 自動変数では扱いきれない大容量オブジェクト(100万個の int配列など)を取り扱う. 34 リpp.118-119配列の自動変数(1)
配列の自動変数(1)
関数の中で配列変数を定義すれば,関数処理の中で確保さ
れ,関数処理が終わると破棄されるような配列が作られる.
れ,関数処理が終わると破棄されるような配列が作られる.
void print_message(void) void print_message(void) { { { {char message[] = "Wakayama"; char message[] = "Wakayama"; printf("%s
printf("%s¥¥n"n" message);message); printf( %s
printf( %s¥¥n , message);n , message); }
}
print_message
message
'W'
'a'
'k'
'a'
'y'
'a'
'm' 'a'
'¥0'配列の自動変数(2)
配列の自動変数(2)
関数の仮引数に配列変数を書けば,その配列と型が適合す
るポインタ変数になる.
るポインタ変数になる.
voidvoid print_messageprint_message(char message[])(char message[]) {
{ 宣言の形は不完全型
printf
printf("%s("%s¥¥n", message);n", message); } } 宣言の形は不完全型 実体はポインタ変数 要素数(多次元配列の場合は左端のみ)は無視される. 要素数なし・初期化なし(不完全型)でもよい. print_message
message
'W'
'a'
'k'
'a'
'y'
'a'
'm' 'a'
'¥0' 36多項式の計算
多項式の計算
仕様
多項式関数 f(x) = c xn + c xn-1 + + c x + c 多項式関数 f(x) = cnx + cn-1x + … + c1x + c0 と実数aが与えられたときに,f(a)を計算する. 考え方
考え方
係数 c0, c1, c2, … cn を,配列変数で保持する. • c は xのi次の係数 • ci は,xのi次の係数 f(a) = (…(cn * a) + cn-1) * a + …) + c0 により求め(ホーナー法) 乗算の回数を減らす により求め(ホーナー法),乗算の回数を減らす. • v0 = cn • v v * a + c • v1 = v0 * a + cn-1 • v2 = v1 * a + cn-2 = cn*a*a + cn-1*a + cn-2 * • vi = vi-1 * a + cn-i 37 polynomial1.c多項式の計算を行う関数
多項式の計算を行う関数
係数の配列(の先頭を
コード(抜粋)
double calc(double f[]double calc(double f[] intint sizesize double x)double x)
係数の配列(の先頭を 指し示すポインタ変数)
double calc(double f[], double calc(double f[], intint size, double x)size, double x)
{ {
double
double valval;; f の配列の要素数(xの次数 + 1) f(x) を求める
ための の値 ; ; int int ii;; val
val = f[size = f[size -- 1];1];
(xの次数 + 1) ためのxの値 v ← cn
for(
for(ii = size = size -- 2; 2; ii >= 0; >= 0; ii----){){ val
val = = valval * x + f[* x + f[ii];]; }
} v ← v*x + cn-i
} }
return
return valval;; } } v = f(x) = cnxn + cn-1xn-1 + … + cnx + c0 } }