引数としての構造体について説明します。
まずは適当な構造体を宣言します。
typedef struct
{
int hp;
int mp;
} Player;
|
この構造体を関数に渡すには変数と同じように考えれば良いです。
以前のプログラムと同じく、ステータスを表示するStatus関数を作ってみます。
プロトタイプ宣言は↓の通り。
void Status(Player player); |
Player構造体でplayerという実体を作り、ここでデータを受け取ります。
本体は構造体を受け取っているので、
void Status(Player player)
{
printf("Player's Status\n");
printf("HP = %d\n", player.hp);
printf("MP = %d\n", player.mp);
}
|
のように書きます。
では、実際に作ってみましょう。
<sample program 138-01>
#include <stdio.h>
typedef struct
{
int hp;
int mp;
} Player;
void Status(Player player);
int main(void)
{
Player player;
player.hp = 100;
player.mp = 50;
Status(player);
return 0;
}
void Status(Player player)
{
printf("Player's Status\n");
printf("HP = %d\n", player.hp);
printf("MP = %d\n", player.mp);
}
|
<実行結果>
Player's Status HP = 100 MP = 50 続行するには何かキーを押してください・・・
※Player構造体は関数の外で宣言しているため、main関数でもStatus関数でも使用可能です。
では、これも以前と同じように戦闘の関数を加えてみたいと思います。
戦闘中に変化したパラメーターは戦闘後にも反映されていなければなりませんので、構造体のアドレスを渡す必要があります。
構造体のアドレスも、実体の先頭に「&」を付けることで表せます。
ポインタ変数も構造体で宣言しますので、Battle関数のプロトタイプ宣言は↓のようになります。
void Battle(Player *pPlayer); |
本体は、hpを50減らし、mpを20減らすよう作ります。
void Battle(Player *pPlayer)
{
pPlayer->hp -= 50;
pPlayer->mp -= 20;
}
|
ここが注目点です。
構造体のアドレスを受け取ってメンバ変数にアクセスする時には「.」ドット演算子ではなく「->」アロー演算子を使います。
当然、「.」ドット演算子を使った場合はエラーになります。
error C2231: '.hp': 左のオペランドが 'struct' へのポインターです。'->' を使用してください。
このようなメッセージが出てきます。
間違えないようにしっかりと覚えておいてください。
では、実際にBattle関数を加えたプログラムを作ってみます。
<sample program 138-02>
#include <stdio.h>
typedef struct
{
int hp;
int mp;
} Player;
void Status(Player player);
void Battle(Player *pPlayer);
int main(void)
{
Player player;
player.hp = 100;
player.mp = 50;
Status(player);
Battle(&player);
Status(player);
return 0;
}
void Status(Player player)
{
printf("Player's Status\n");
printf("HP = %d\n", player.hp);
printf("MP = %d\n", player.mp);
}
void Battle(Player *pPlayer)
{
pPlayer->hp -= 50;
pPlayer->mp -= 20;
}
|
<実行結果>
Player's Status HP = 100 MP = 50 Player's Status HP = 50 MP = 30 続行するには何かキーを押してください・・・
構造体にも「値渡し」と「アドレス渡し」があることが分かりました。
「値渡し」よりも「アドレス渡し」の方が効率が良いのですが、この話はまた後でしましょう。