関数の基本
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)
平均値を求まる関数を作成してください。