関数(引数と戻り値について2)で完成出来なかったプログラムをポインタ変数を使って完成させましょう。
完成出来なかった理由は↓の通りです。
<sample program 132-03>
#include <stdio.h> void Status(int hp, int mp); int Battle(int hp, int mp); int main(void) { int hp; int mp; hp = 100; mp = 50; Status(hp, mp); hp = Battle(hp, mp); Status(hp, mp); return 0; } void Status(int hp, int mp) { printf("Player's Status\n"); printf("HP = %d\n", hp); printf("MP = %d\n", mp); } int Battle(int hp, int mp) { hp -= 50; mp -= 20; return hp; } |
<実行結果>
*p = 133 続行するには何かキーを押してください・・・
Battle関数にhpとmpを渡して、戦闘を行うシミュレーションを行ったが、戻り値としてhpを戻すとmpが戻せない。
mpが戻せないので、戦闘終了後のステータスを表示するとmpは増減していないことになってしまう。
これが問題でした。
これを解決するため「ポインタ変数」と「アドレス渡し」を説明しました。
ポインタ変数を使って、アドレスを渡すことでmain関数の変数の中身を別の関数で書き換えることが出来るようになります。
hpやmpも「値」ではなく「アドレス」を渡すようにすればreturn文で戦闘後の数値を戻さなくてもよくなります。
では、改良してみましょう。
前回のプログラムなどを参考にして作り変えてみてください。
一応、Battle関数のプロトタイプ宣言だけは書いておきます。
void Battle(int *pHp, int *pMp); |
関数名 Battle 引 数 int型変数のアドレス(変数hpのアドレス) int型変数のアドレス(変数mpのアドレス) 戻り値 不要になりますのでvoid(なし)です。
※ポインタ変数の先頭には頭文字「p」を付けることにします。
解答例です。
<sample program 135-01>
#include <stdio.h> void Status(int hp, int mp); void Battle(int *pHp, int *pMp); int main(void) { int hp; int mp; hp = 100; mp = 50; Status(hp, mp); Battle(&hp, &mp); Status(hp, mp); return 0; } void Status(int hp, int mp) { printf("Player's Status\n"); printf("HP = %d\n", hp); printf("MP = %d\n", mp); } void Battle(int *pHp, int *pMp) { *pHp -= 50; *pMp -= 20; } |
<実行結果>
Player's Status HP = 100 MP = 50 Player's Status HP = 50 MP = 30 続行するには何かキーを押してください・・・
Battle関数に変数hp、変数mpのアドレスを渡すことによって戦闘後のステータスもきちんと変えることが出来ました。
関数の引数を考える場合、「値渡し」が良いのか、「アドレス渡し」が良いのか、よく考えてから作る必要があるということです。