授業/C言語基礎/関数 のバックアップ差分(No.5)


  • 追加された行はこの色です。
  • 削除された行はこの色です。
これまでに、標準で用意されている関数として、printf関数、scanf関数、rand関数、srand関数、time関数を使ってきました。

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



*関数の呼び出し [#u320153f]

プログラムの中で関数を使うことを、関数の''呼び出し''といいます。
関数を呼び出すときは、必ず、関数の名前の後に括弧 ( ) を付けます。

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

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

たとえば、srand関数は、乱数のシードを引数として受け取り、結果を返さない関数です。
#geshi(c){{
  srand(1);
}}

rand関数は、引数なしで、int型の値を戻り値として返す関数です。
#geshi(c){{
  int r = rand();
}}

普通の関数は引数の数が決まっていますが、printf関数とscanf関数のように、引数の数が決まっていない関数もあります。
#geshi(c){{
  int i = 0;

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

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



*関数の定義 [#i5bd75d0]

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



**引数と戻り値がある関数の定義 [#na622bb2]

関数を定義するには、次のようにします。
#geshi(c){{
戻り値の型 関数の名前(引数1の型 引数1の名前, 引数2の型 引数2の名前, ...) {
  処理
  return 戻り値;
}
}}

たとえば、二つのint型の値の和を返す関数absを次のように定義できます。
#geshi(c){{
int add(int x1, int x2) {
  int y = x1 + x2;  
  return y;
}
}}

これを呼び出すプログラムは、次のようになります(プログラム1)。
#geshi(c){{
#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 [#mbf19437]

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



**引数がない関数の定義 [#oedbd187]

引数がない関数を定義するときは、仮引数として void と定義します。
#geshi(c){{
戻り値の型 関数の名前(void) {
  処理
  return 戻り値;
}
}}
呼び出すときは、引数に何も指定しません。

たとえば、サイコロを振る(引数がない)関数を定義すると、次のようになります(プログラム2)。
#geshi(c){{
#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 [#he2b796c]

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


**戻り値がない関数の定義 [#ib9cc723]

戻り値がない関数を定義するときは、戻り値の型として void と定義します。
また、return文には、戻り値を指定しません。
(関数の最後にある戻り値のないreturn文は、省略できます。)
#geshi(c){{
void 関数の名前(引数) {
  処理
  return;
}
}}

たとえば、指定された回数Hello World!と表示する(戻り値がない)関数を定義すると、次のようになります(プログラム3)。
#geshi(c){{
#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 [#hf18b253]

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



*特別な関数 main [#o5e6ede1]

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

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

main関数は次のように定義していました。
#geshi(c){{
int main(void) {
  処理
  return 0;
}
}}
これは、名前がmainで、引数なし、戻り値がint型の関数です。

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

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

main関数は、特別に、return文を省略でき、省略すると 0 が返されます。
また、main関数は、特別に、戻り値の型の宣言を省略できます。
#geshi(c){{
int main(void) {
  printf("Hello World!\n");
}
}}
#geshi(c){{
main(void) {
  printf("Hello World!\n");
  return 0;
}
}}

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

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




*関数の中で宣言した変数の有効範囲 [#t4ba4657]

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

次のプログラム(プログラム4)では、print1関数とmain関数のそれぞれで変数 i が宣言されています。
次のプログラムでは、print1関数とmain関数のそれぞれで変数 i が宣言されています(プログラム4)。
#geshi(c){{
#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 のままで変更されません。

これを実行すると、次のようになります。
#geshi(sh){{
luna% a.out
1
0
}}


**演習4 [#h043e1bd]
プログラム4を作成し、実行結果を確認せよ。



*関数の宣言 [#m641e5fc]

関数を使うためには、呼び出すよりも前に、関数を宣言する必要があります。
関数を使うには、呼び出すよりも前に、関数を''宣言''する必要があります。

関数は、次のように宣言します。
#geshi(c){{
戻り値の型 関数の名前(引数1の型 引数1の名前, 引数2の型 引数2の名前, ...);
}}

ただし、関数を呼び出すよりも前に定義しているときは、関数の宣言を省略できます。
ただし、呼び出すよりも前に関数を「定義」しているときは、関数の「宣言」を省略できます。
実は、これまでは、関数を呼び出すよりも前に定義して、関数の宣言を省略していました。

たとえば、プログラム1で作成したadd関数を呼び出すよりも後に定義する場合は、次のように宣言します(プログラム5)。
#geshi(c){{
#include <stdio.h>

int add(int x1, int x2);


int main(void) {
  int i = 1, j = 2, k;
  
  k = add(i, j);
  printf("%d\n", k);
  
  return 0;
}


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


**演習5 [#h92722f0]

プログラム1をプログラム5に変更し、実行結果を確認せよ。

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS