関数

2024-03-22 (金) 12:00:22 (28d) | Topic path: Top / 授業 / C言語基礎 / 関数

これまでに、標準で用意されている関数として、printf関数、scanf関数、rand関数、srand関数、time関数を使ってきました。

これらは、それぞれ特定の機能を実行するための処理をまとめたもので、これを関数といいます。

関数の呼び出し

プログラムの中で関数を使うことを、関数の呼び出しといいます。

関数を呼び出すときは、必ず、関数の名前の後に括弧 ( ) を付けます。

( ) の中には、関数に渡す変数を記述します。 関数に渡す変数のことを引数といいます。 複数の引数を渡すときは、引数をコンマ , で区切って指定します。

また、呼び出すと、その結果を返してくれる関数もあります。 返してくれる値のことを戻り値といいます。

たとえば、srand関数は、乱数のシードを引数として受け取り、戻り値を返さない関数です。

  srand(1);

rand関数は、引数なしで、int型の値を戻り値として返す関数です。

  int r = rand();

普通の関数は引数の数が決まっていますが、printf関数とscanf関数のように、引数の数が決まっていない関数もあります。

  int i = 0;

  printf("Hello World!\n");
  printf("i = %d\n", i);

ちなみに、printf関数とscanf関数はint型の値を戻り値として返しますが、これまで、戻り値を無視していました。 printf関数は出力した文字数を、scanf関数は代入された値の数を返します。

関数の定義

関数は自分で作ることができます。 関数を作ることを、「関数を定義する」といいます。

引数と戻り値がある関数の定義

関数を定義するには、次のようにします。

戻り値の型 関数の名前(引数1の型 引数1の名前, 引数2の型 引数2の名前, ...) {
  処理
  return 戻り値;
}

同じ型の引数を複数使うときでも、型を省略できないことに注意しましょう。

たとえば、二つのint型の値の和を返す関数addを次のように定義できます。

int add(int x1, int x2) {
  int y = x1 + x2;  
  return y;
}

これを呼び出すプログラムは、次のようになります(プログラム1)。

#include <stdio.h>

int add(int x1, int x2) {
  int y = x1 + x2;  
  return y;
}


int main(void) {
  int i = 1, j = 2, k;

  k = add(i, j);
  printf("%d\n", k);

  return 0;
}

このように、引数として渡す変数の名前と引数として受け取る変数の名前が同じである必要はありません。

演習1

プログラム1を作成し、実行結果を確認せよ。

引数がない関数の定義

引数がない関数を定義するときは、仮引数として void と定義します。

戻り値の型 関数の名前(void) {
  処理
  return 戻り値;
}

呼び出すときは、引数に何も指定しません。

たとえば、サイコロを振る(引数がない)関数を定義すると、次のようになります(プログラム2)。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int dice(void) {
  int r = rand() % 6 + 1;
  return r;
}


int main(void) {
  int r;

  srand((unsigned int) time(NULL));  // 乱数のシード
  r = dice();

  printf("%d\n", r);

  return 0;
}

演習2

プログラム2を作成し、実行結果を確認せよ。

戻り値がない関数の定義

戻り値がない関数を定義するときは、戻り値の型を void として定義します。 また、return文には、戻り値を指定しません。 (関数の最後にある戻り値のないreturn文は、省略できます。)

void 関数の名前(引数) {
  処理
  return;
}

たとえば、指定された回数Hello World!と表示する(戻り値がない)関数を定義すると、次のようになります(プログラム3)。

#include <stdio.h>

void hello(int n) {
  int i;

  for (i = 1; i <= n; i++) {
    printf("Hello World!\n");
  }

  return;
}


int main(void) {
  hello(5);

  return 0;
}

演習3

プログラム3を作成し、実行結果を確認せよ。

特別な関数 main

実は、これまでのプログラムでも、関数を定義していました。

それが、特別な関数、main関数です。

main関数は次のように定義していました。

int main(void) {
  処理
  return 0;
}

これは、名前がmainで、引数なし、戻り値がint型の関数です。

main関数は、プログラムが実行されたときに、最初に呼び出されます。

プログラムが終了すると、main関数の戻り値がOSへ返されます。 main関数から 0 が返されると、OSはプログラムが正常に終了したと判断し、1 が返されると、OSはプログラムが異常に終了したと判断します。

main関数は、特別に、return文を省略でき、省略すると 0 が返されます。 また、main関数は、特別に、戻り値の型の宣言を省略できます。

int main(void) {
  printf("Hello World!\n");
}
main(void) {
  printf("Hello World!\n");
  return 0;
}

昔は、main関数の戻り値はありませんでした。 ですから、古い教科書では、main関数の戻り値の型をvoidとしているものがあります。 今は、main関数の戻り値の型をvoidにすることはできません。

また、main関数には、プログラムを実行するときに指定されたコマンドライン引数を渡すことができます。 コマンドライン引数については、もう少し先に進んでから後で勉強します。

関数の中で宣言した変数の有効範囲(おまけ)

関数の中で宣言した変数は、その関数の中だけで有効です。

次のプログラムでは、print1関数とmain関数のそれぞれで変数 i が宣言されています(プログラム4)。

#include <stdio.h>

void print1(void) {
  int i = 1;
  printf("%d\n", i);
}

int main(void) {
  int i = 0;

  print1();
  printf("%d\n", i);

  return 0;
}

main関数で宣言された変数 i とprint1関数で宣言された変数 i は、コンピューターのメモリーの中では別の場所に記憶されていて、同姓同名の別人のように、同じ名前だけど別の変数として扱われます。 最初にmain関数において変数 i に 0 を代入し、その後、print1関数において変数 i に 1 を代入していますが、print1関数で宣言された変数 i はmain関数で宣言された変数 i とは別の変数なので、print1関数の変数 i に 1 を代入してもmain関数の変数 i の値は 0 のままで変更されません。

これを実行すると、次のようになります。

luna% a.out
1
0

演習4

プログラム4を作成し、実行結果を確認せよ。


まとめ

複数の処理をまとめたものを関数といい、プログラムの中に関数を用意することを「関数を定義する」、プログラムの中で関数を使用することを「関数を呼び出す」といいます。

関数を呼び出すときに関数に渡す値を引数といい、関数が戻す値を戻り値といいます。

引数がない関数も定義できます。 引数がない関数を定義するときは、引数として仮引数 void を指定します。

戻り値がない関数も定義できます。 戻り値がない関数を定義するときは、戻り値の型として void を指定します。

関数の中で宣言された変数は、その関数の中だけで有効です。 他の関数からは見えません。


練習問題

練習問題はこちら

トップ   編集 凍結解除 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS