講習No.11

復習
前回の関数のまとめ(1)
関数はmain()関数または他の関数から呼び出されて実行される.
関数を呼び出す側の実引数の値が関数内の仮引数(変数)に
コピーされる
関数内で求めた値はreturn文によって関数値として呼び出し側に戻される.
#include <stdio.h>
関数の定義
float menseki(float a, float b)
{
return (a * b / 2);
}
a, b: 仮引数
仮引数もローカル変数
→関数内でのみ有効
int main(void)
{
float x, y, kekka;
printf("底辺は?"); scanf(" %f ", &x);
printf("高さは?"); scanf(" %f ", &y);
関数の呼び出し
}
kekka = menseki(x, y);
printf("面積は%fです.¥n", kekka);
x,y:実引数
復習
前回の関数のまとめ(2)
関数はプログラム上の部品(機能単位)である.
関数内の変数はお互いに独立である(干渉しない).
#include
<stdio.h>
float menseki(float a, float b)
{
float s;
s = a * b / 2;
return s;
}
menseki()関数
同じ変数名a,bでも,関数
が違うと,別の変数と見な
される
main()関数
int main(void)
{
float a, b, kekka;
printf("底辺は?"); scanf(" %f ", &a);
printf("高さは?"); scanf(" %f ", &b);
kekka = menseki();
printf("面積は%fです.¥n", kekka);
}
関数定義におけるreturn 文
float menseki(float a, float b)
{
float s;
s = a * b / 2;
return s;
}
int func(int x, int y)
{
if (x*y % 2 == 0)
{
return 1;
}
}
return文を実行し
ない場合があるの
でダメ.
復習
float menseki(float a, float b)
{
return a * b / 2;
}
return文の文法
return 式;
int func(int x, int y)
{
if (x*y % 2 == 0) return文を実行すると関
数を終了する.式の値
{
を関数値として戻す.
return 1;
}
else
{
return文は複数あって
return 0;
もOK.但し,どのような
}
場合でも必ずその一つ
}
を実行すること.
return文で戻る値を返り値
あるいは戻り値と呼ぶ
関数の戻り値
float menseki(float a, float b)
{
float s;
s = a * b / 2;
return s;
}
int main(void)
{
float x, y;
printf("底辺は?"); scanf("%f", &x);
printf("高さは?"); scanf("%f", &y);
menseki(x, y);
printf("計算はしたよ\n");
}
menseki()関数の
戻り値が変数に代
入されていない!
質問 これはコンパイル
エラーになるか?
printf(・・・)
scanf(・・・)
main()
これらは全て関数
但し,一般に戻り値は
利用されない
答え エラーにはならない.
関数値の戻り値は代入され
なくてもかまわない.
void キーワード
関数値を持たない(返さない)関数の定義
voidは戻
り値が無
いことを
宣言
void kansu(float a, float b)
{
何も返さないので,return 式 ;
....
とは書かない.
return;
return文の省略も可能!
}
int main(void)
{
int x;
x = kansu(3, 4);
printf("x=%d, %d", x, kansu(2,5));
}
void 宣言された
関数の関数値を
利用しようとする
とエラー
引数としてvoidと書くと,
引数が無いことを宣言
int func(void)
{
return 5;
}
int main(void)
{
printf("値は%d", func());
}
main()関数
関数値は
int型
(関数値を戻す)
int func(void)
{
return 5;
}
voidなので
引数は無い
int main(void)
{
printf("値は%d", func());
}
void 宣言されていない関数
ではreturn文は省略できな
いはず!!
main()関数は特殊な関数である
関数の戻り値のまとめ
戻り値がある関数でも,必要がなければ,呼び出し側でそれを使
わなくても(代入しなくても)かまわない.
戻り値が無い関数を定義する場合,あらかじめvoid宣言をする.
この場合,return文で値を戻さない.また,return文自体も省略可.
void宣言された関数で戻り値を利用しようとするとエラーになる.
void mul10(int a)
{
a = a * 10;
return;
}
int main(void)
{
int x = 12;
mul10(x);
printf("x = %d", x);
}
x = 12
??
引数を10倍す
る関数
疑問
なぜこのmul10()関数は
意図どおりに働かないか?
引数の値渡し
int main(void)
{
int x = 12;
mul10(x);
printf("x = %d", x);
}
引数を10倍
する関数
void mul10(int a)
{
a = a * 10;
return;
原則 引数のコピーが関数
}
に渡され,呼び出し側の
変数は変化しない.
⇒値渡し(call by value)
x = 12
main()関数
変数
12
関数呼び出し
mul10()関数
引数の値のコピー
x
局所変数
ローカル変数
120
12
a
return文実行
例外
ポインタ引数,配列引数
⇒参照渡し(call by reference)
配列を引数とする関数
#include
n個のデータの合計を求め
る関数
<stdio.h>
int sum(int data[], int n)
{
int s = 0, i;
for (i = 0; i < n; i++)
{ s = s + data[i]; }
return s;
}
int main(void)
{
int i, aa[50], s;
データの個数がn個
(≠配列宣言の要素数)
理由:配列宣言時の要素数と有効なデータ数は
同じではないので!
データを入れる配列
要素数を空欄にする.→data[n]× data[0]×
// 配列aa[]に30個のデータを入力する
・・・
//省略
s = sum(aa,30);
printf(“データの合計は%d\n”,s);
aa[0]からaa[29]に30個の値
を代入しておく
関数呼び出し
配列名のみ書く.[ ]は不要
有効なデータの個数は30個
}
配列引数は自動的に参照渡しだが,この例では配列要素の値は変化させていない
配列引数(参照渡し)を用いた関数
#include
<stdio.h>
void mul10(int data[], int n)
{
int i;
for (i = 0; i < n; i++)
{ data[i] = data[i]*10; }
}
n個のデータの値を10倍す
る関数
関数宣言と引数の書き方
は同じ
配列引数は参照渡しである
ため,呼び出し側の配列の
値が変化する!
int main(void)
{
int i, aa[50], s;
// 配列aa[]に30個のデータを入力する
・・・
//省略
関数の呼び出し方法も同じ
mul10(aa,30);
printf(“データを全て10倍すると”);
・・・
//データの表示(省略)
}
参照渡しにより配列要素の値を変化させる例
配列aa[0]~aa[29]の値は
全て10倍されている.
引数のまとめ
値渡し(基本)
関数を呼び出した側の実引数の値が変化しない.
配列引数とポインタ引数を除く他の全ての引数
参照渡し(例外)
関数を呼び出した側の実引数の値が変化する.
以下の二つのみ.
 配列引数
 ポインタ引数(2年で学習)
関数のデバッグ
[A] ツールバーでデバッグを始める手順
(1) ツールボタンで右クリックして,デバッグを選ぶ
(2) デバッグツールバーからボタンを選ぶ
(3)
(1)ステップオーバー
(2) ステップイン
(3) デバッグの中止
(2)
(1)
次の行を実行
次の行を実行
デバッグをやめる
[B] メニューでデバッグを始める手順
デバッグメニューで,ステップオーバーを選ぶ
ステップインは関
数内部に入って
1行づつ実行す
る