関数

Last-modified: 2021-12-08 (水) 17:33:52
 

関数とは

printf 関数や scanf 関数などを今まで利用してきました。
このように、ある処理をまとめて名前をつけたものを関数と呼びます。

関数は次のように呼び出します。

関数名(引数1, 引数2, 引数3, ...);

printf 関数や scanf 関数などは、あらかじめ用意されている関数です。
C言語では、用意されている関数を使うだけではなく、新しく関数を作ることができます。

main 関数

実は、みなさんは既に関数を作ったことがあります。
main という名前の関数です。

int main(){
    ...
    return 0;
}

main という関数は、プログラム中のどこからも呼び出していません。
この関数は特別な関数であり、プログラム実行時にシステムから呼び出されます。

この main 関数の中から呼び出す関数を、今から定義していきたいと思います。

関数の例

ある整数 a と b を足す関数 add を考えてみます。
関数 add は a と b を足し、その結果を返します。

int add(int a, int b){
    int ans = a + b;
    return ans;
}

この関数は次のように利用します。

printf("%d\n", add(4, 5));

値を返すとは、関数を呼び出した後にどのような値になるかという意味です。
この返す値のことを、戻り値もしくは返り値と呼びます。

値を返すには、return 文を使用します。
main 文の return は呼び出し元であるシステムに値を返しているのです*1

注意

return 文を実行すると、そこで値を返して実行中の関数が終了します。

int f(){
    int a, b;
    a = 1;
    return a;
    // これより下は実行されない
    b = 2;
    return b;
}

関数を作る

関数を作るには、宣言 (プロトタイプ宣言) と定義が必要です。
ただし、宣言は省略される場合もあります。

関数の宣言

関数の宣言は次のようなものです。

int add(int a, int b);

一般化すると次のように表せます。

戻り値の型 関数名(引数の型 引数の変数名, ...);

関数の宣言は main 関数の外で行います。

宣言には関数の本体を含みません
stdio.h や math.h などのヘッダファイルにはこれらの関数の宣言が書かれています。

関数の宣言は、コンパイラに関数の存在を知らせる為にあります。
関数の宣言が無くても、関数が定義されていれば正常にコンパイルされます

関数の定義

関数の定義は次のようなものです。

int add(int a, int b){
    return a + b;
}

一般化すると次のように表せます。

戻り値の型 関数名(引数の型 引数の変数名, ...){
    ...
    return 戻り値;
}

関数の定義は main 関数の外で行います。

関数に渡された引数は、関数定義に書いた変数名で利用できます。
この変数は、関数の内部だけで有効です。

引数について

int main() {
    int a, b;
    a = 3;
    b = 5;
    printf("%d\n", sub(a, b));

    return 0;
}

int sub(int c, int d){
    return c - d;
}

関数を呼び出す際、記述したとおりの順番で引数に入ります。この例では c に 3、d に 5 が渡され、-2 が出力されます。
もし順番を入れ替えると、2 が出力されます。

宣言と定義の使い方

関数宣言の無い以下のようなプログラムがあったとします。

 #include <stdio.h>

 int main(){
    printf("%d\n", add(4, 5));

    return 0;
 }

 int add(int a, int b){
    return a + b;
 }

上のコンパイルは正常に実行できますが、コンパイル時にwarning が出ます*2

これを防ぐには、main 関数の上に、次のようなプロトタイプ宣言を書きます。

int add(int a, int b);

戻り値の無い関数

戻り値の無い関数は、戻り値の型を void とします。
void は戻り値が無いことを表す特別な型で、void 型の変数をつくることはできません*3

Hello World と表示する関数 hello の例です。

void hello(){
    printf("Hello World\n");
}

課題

課題1

次のようなプロトタイプ宣言で表される関数 power を作りなさい。
ただし、power 関数は a (a > 0) の b (b > 0) 乗を返すものとする。

int power(int a, int b);

また、作成した関数を使い、a の b 乗を求めるプログラムを作りなさい。

実行例

./a.out
3 2
9

課題2

課題1で作成した power 関数を用い、以下のプロトタイプ宣言で表される関数 power2 を作りなさい。
ただし、power2 関数は a (a > 0) の2乗を返すものとする。

int power2(int a);

また、作成した関数を使い、a の2乗を求めるプログラムを作りなさい。

実行例

1つの整数を入力します。
入力した整数の2乗を出力します。

./a.out
6
36

挑戦課題

補足

入力の最後まで読み込むのは、以下のようにします。

while(scanf("%d", &x) != EOF){
    ...
}
 


*1 その値は、環境変数 $? で参照できます
*2 環境によっては warning が出ないことがあります。その場合は、gcc -W -Wall とコンパイルしてください。
*3 void 型のポインタは作れます