関数
関数は ---ひとことで言えば--- サブルーチンです。
もうちっと丁寧に説明すると、
[数学の関数]と[サブルーチン]の概念を融合した制御構造
です?
実はうつろさん数学よりプログラミングの方が経験豊富で、数学の関数の概念がすでに忘却の彼方な状態でス。
HSPで言えば、命令やサブルーチンに近い、
#deffuncで定義されるユーザ定義の命令に非常に近い、
そんな概念です。
関数には、値を返すものと値を返さないものがあります。
[数学の関数]的なCの関数は値を返す関数の一種であり、
値を返さない関数は[サブルーチン]そのものといってよいでせう。
○「値を返す」
例えば加算の演算で
a = 1+2;
こういう処理があった場合、
「1+2」という式は値「3」を返す(演算子+は1と2の和を返す)
という発想をするもんです。
int add(int a,int b){
return a+b;
}
こういう関数を作ったとします。これは、加算演算子と同じような働きをする関数で、
これを定義した後に
a = add(1,2);
とすると、先に提示した処理文と基本的に同じ処理になります。この場合は
関数addは1と2の和を返す
という見方をするわけなのです。
○戻り値、引数
返された値のことを「戻り値(返り値)」と呼んだりします。
また、関数に渡す値のこと(上例だと1と2)を引数(ひきすう)と呼びます。
よくあるC言語らしい関数というのは、何かのまとまった処理をしてもらった後、
処理結果の報告を戻り値として返すものです。
(HSPでは、システム変数statが戻り値の役割をになっていることが多いです。)
例えば、HSPのbload命令のような関数を作ってみるとき。
bload(ファイル名,バッファ){
ファイルをオープンする;
ファイル内容をバッファに転送する;
ファイルをクローズする;
}
というような実装になると思われます。この時に、
各処理のどこかでエラーが発生したら偽の値を返し
問題なく処理できたら真の値を返す
ような関数にしておけば、bload関数を使う際に
if(bload("hoe.txt",buf) == FALSE){
/* エラー処理 */
}
のような書き方が出来て、慣れると非常に使いやすいのですよ。
つまりは、「値を返すサブルーチン」という印象が強いのが関数です。
○関数の定義
(戻り値の型) 関数名(引数1,引数2,…){
関数内変数の宣言
…
処理の内容
…
return 返す値;
}
一般的には、このような雛型になるでせう。
(戻り値の型)
値を返さない関数の場合は、voidとして宣言します。
値を返す関数は、その戻り値の型を書きます。
引数
引数をとらない関数の場合は、引数欄に何も書かず()で閉じます。
引数をとる関数の場合は、それぞれの引数欄に
(引数の型) (引数として使用する変数名)
を書きます。
return
処理がreturn文に到達した時は、その場で関数を抜けます。
値を返す関数の場合は、返す値欄に値を書いておくと、その値を返します。
値を返さない関数の場合は、処理が中コッカに到達した時点で関数を抜けます。
returnで抜けても構いませんが、返す値は書かないように。
returnは、(可読性を考えると最後にあるのがベターだと思いますが)
必ずしも関数の最後におく必要はありません。
サンプルをば。階乗を返す関数、でう。ちょっとCっぽいコーディング。
#include <stdio.h>
int pow(int a){
int r=1;
if (a<0) return 0; /* 失敗 */
while(a){
r *= a;
a--;
}
return r;
}
int main(){
printf("%d\n",pow(1));
printf("%d\n",pow(5));
printf("%d\n",pow(10));
return 0;
}
(出力)
1
120
3628800
再帰関数にするよりは速いっす。ホホホ
○関数内変数、ローカル変数、自動変数、static変数
関数内では、その関数の中でだけ使用可能な変数を定義できます。
関数内で宣言された変数は、
その関数の外部からその変数名を使ってアクセスすることはできません。
このように、アクセス可能な範囲が限定されている変数をローカル変数といいます。
また、その範囲のことを「スコープ」と呼んだりします。まんまだ。
自動変数(auto変数)
関数内変数のうち、static変数(後述)でないものを自動変数といいます。
この変数は、関数が呼ばれるたびに生成され、
その関数から抜ける際にそっこーで殺されます。
つまり、以前にこの関数が呼び出されていたとしても、新しく生まれ変わった
その自動変数はかつての記憶は完全に失われているということです。
記憶が戻ることは未来永劫ありえません。愛の力をもってしても。
ひとりボケはむなしいなあ
この変数は、初期値なしで生成された時の値は不定です。
0でクリアされている、と思ってはいけません。
関数内static変数(静的変数)
関数内変数で、自動変数でないものです。 れトリッキー
つまり、以前にこの関数が呼び出されていたとしても、新しく生まれ変わっていない
そのstatic変数はかつての記憶は完全に失われていないということです。
記憶を戻す必要は未来永劫ありえません。愛の力もいりません。
ひとりボケはむなしいなあ
static変数は、プログラム全体の起動時に一度だけ生成、初期化されます。
static int a=5;
と宣言されているものは、初期化時にだけ5が代入され、関数呼び出し時にも
以前の値が保持されています。
#include <stdio.h>
void printvalue(){
int a=2;
static int b=2;
a++;
b++;
printf("a = %d,b = %d\n",a,b);
}
int main(){
printvalue();
printvalue();
printvalue();
printvalue();
printvalue();
return 0;
}
(出力)
a = 3,b = 3
a = 3,b = 4
a = 3,b = 5
a = 3,b = 6
a = 3,b = 7
static変数は記憶力をお持ちである。ということで。