関数の基本
C言語において関数を使うことには、以下のような利点があります。
関数化しておくとそれを1つのブラックボックスとして扱うことができます。 つまり、使用する側が知っておくべきことは、以下の通りです。
- 入力として、どのような引数を与えるか
- 出力として、関数がどんな値を返すのか
- 関数を使ったことによって、どんな副作用があるか
- 一度、関数として作成しておけば、後で何度でも再利用することができる
- 関数として各機能をまとめていくと、一般にプログラムが見やすく、デバッグの作業もしやすい
関数の呼び出し
#include <stdio.h> void func(); //関数のプロトタイプ宣言 int main() { func(); //関数呼び出し printf(" ここがメイン関数内\n"); return 0; } void func() //自作関数 { printf("ここは自作関数内\n"); return; //「return;」は省略可 }
関数定義
関数の定義
戻り値の型 関数名(パラメータリスト) { 文 ... }
関数プロトタイプ宣言
戻り値型 関数名(パラメータリスト);
戻り値の型、関数名、引数のルールは関数を作る際とほとんど同じです。但し、プロトタイプ宣言する行の最後には「;」が必要。
Void Type関数
void型は、今までの数値型や文字型とは異なり、戻り値が無い関数のデータ型のことです。処理の結果を戻す必要が無い場合は、わざわざint型にして「return 0;」としなくても、void型で関数を定義すれば、最後にreturn文を書く必要はありません。
- 値を返さない return型に用いる
- 引数が無い場合に用いる
関数へ値を渡す
値
C言語では、関数へ情報を渡す場合、必ず元の変数の値のコピーを渡します。
この様な方法を値渡しと呼び、元の変数の値が変更されないことが特徴です。
「値渡し」, ex : printf()
#include <stdio.h> void plus1(int x) { x = x + 1; } int main(int argc, const char * argv[]) { // insert code here... int a; a = 1; plus1(a); printf("a = %d\n", a); return 0; }
アドレス
「参照渡し」, ex : scanf()
ポインタ型の引数であっても、値のコピーが渡される原則に違いはありません。
それでもポインタ型を使うのは、ポインタ型はアドレスを受け取ることが出来るからです。
#include <stdio.h> void plus1(int *x) { *x = *x + 1; } int main(int argc, const char * argv[]) { // insert code here... int a; a = 1; plus1(&a); printf("a = %d\n", a); return 0; }
配列
関数に配列を丸ごと渡すことができません。あたかも配列を丸ごと渡すように書くことができます。
#include <stdio.h> void func(int [10]); int main(void){ int figure[10]={1,2,3,4,5,6,7,8,9,10}; func(figure); return 0; } void func(int temp[10]){ for(int i=0;i<10;++i){ printf("%d\n",temp[i]); } } void func2(int temp[]){ for(int i=0;i<10;++i){ printf("%d\n",temp[i]); } } void func3(int *temp){ for(int i=0;i<10;++i){ printf("%d\n",*(temp+i)); } }
func, func2, func3は全く同じ機能する。
配列を丸ごと渡すように書くだが、実質参照渡しなので、下記のおかしな現象が発生する。
- 配列の要素数は無視される
- 関数内で配列の値を変えると呼び出し側まで変化する
演習
ABクラス
a-8-1-2 (p266)
曜日を求まる関数を作成してください。
CDクラス
a-8-3-2-1 (p276)
平均値を求まる関数を作成してください。