👆このことは ゲームキャラクターが移動することやゲームキャラのHPやMPの値が変化することと関係しています 

配列宣言を自作関数の引数に設定し自作関数の実行時main関数内で定義された配列のアドレスを格納したポインタ変数を代入することができます。参照渡し(ポインタ渡し)となり値渡しされる方法はありません 

アレサ「配列のアドレスを格納しているポインタ変数を


自作関数の引数となっている配列宣言に渡すときは


参照渡し(ポインタ渡し)になっているか値渡しとなっているかどうか


ということですか・・・



ではすこしだけ おさらいしてみますか😊



次のプログラムをご覧ください

👇

#include <stdio.h>



void newmadefunction(int* ptx) {


*ptx = *ptx * 2;


}



int main() {

int a = 1;


newmadefunction(&a);


printf("%d\n", a);


return 0;

}


ビルド実行結果


2


アレサ「


自作関数

newmadefunctionの定義が

👇

void newmadefunction(int* ptx) {


*ptx = *ptx * 2;


}


のように設定されているとします



newmadefunction(&a);


を実行して


main関数内で変数宣言された変数aのアドレス&aを


自作関数newmadefunction(int* ptx)の引数となっているポインタ変数宣言


int* ptx;


で定義されたポインタ変数ptxに


ptx=&a;


と代入すると


変数aのアドレスの場所のメモリに格納されている数値データは


*ptxであらわされます


*ptxは変数aのアドレスの場所のメモリにアクセスするための


窓であり


その窓を通して


変数aのアドレスの場所のメモリに格納されている数値データ


を変更することができます。


*ptxに


*ptx=5;

*ptx=10;

*ptx=1000;


などのように


*ptxに数値を代入して


つまり


変数aのアドレスの場所のメモリに数値を代入して


変数aのアドレスの場所のメモリにある数値を変更すると


main関数内で定義された変数aに格納されている値が


5

10

1000


と変更されます


main関数内で


int a = 1;


が実行されているので


変数aは1の値をもつことになります


ptx=&a;


が実行されているので


変数aのアドレスの場所のメモリに格納されている数値データは


*ptxであらわされます


ですので


変数aが1の値をもつと


*ptxは1の値をもつことになります


*ptxが1をあらわす今の状態では



*ptx = *ptx * 2;


が実行されたなら


*ptx は2の値をもつことになりますので


変数aに格納されている数値データは2となります



このように


自作関数の引数となっているint* ptx(ポインタ変数ptx)に


main関数内で変数宣言された


            💖変数aのアドレス💖


を代入する方法を


参照渡し(ポインタ渡し)とよびます。


前のエピソードでは


自作関数の引数である


int hairetu[]に


配列newhairetuのアドレスを格納しているポインタ変数


newhairetuを代入し


main関数内で定義された配列newhairetuの


配列変数


newhairetu[0]

newhairetu[1]

newhairetu[2]

newhairetu[3]

newhairetu[4]


に格納されている数値データを変更しました


このときも


自作関数の引数となっている int hairetu[](結局はポインタ変数hairetu)に


main関数内で配列宣言された


          💖配列newhairetuのアドレスを格納している💖


               💖ポインタ変数newhairetu💖


代入しているので


参照渡し(ポインタ渡し)になっています」



ソーラー「そうだね 


今 きづいたんだけど


このように


main関数で配列宣言され作製された


配列変数に格納された数値データを


自作関数をつかって操作を加えるには


自作関数の引数として

配列宣言

int hairetu[]


もしくは

ポインタ変数宣言

int* hairetu


を設定し


自作関数の引数となっている

配列宣言

int hairetu[]


もしくは

ポインタ変数宣言

int* hairetu




ポインタ変数newhairetuを代入する方法しか


C言語では設定されてないよね」


アレサ「ほんとですね


ポインタ変数をつかうしかないとなると


 参照渡し(ポインタ渡し)


 しかないことになります


(だからポインタ渡しと呼ばれています)



 参照渡し(ポインタ渡し)がおこなわれると


main関数内で配列宣言された配列newhairetuに


格納された数値データは


自作関数によって操作し変更することができますね。


それではもうすこしだけ


自作関数の引数となっている


int hairetu[]


もしくは


int* hairetu


にポインタ変数newhairetuを


参照渡し(ポインタ渡し)して


main関数内で配列宣言された配列newhairetuの配列変数


newhairetu[0]

newhairetu[1]

newhairetu[2]

newhairetu[3]

newhairetu[4]

に格納されている数値データ


が変化する様子をみてみましょうか。



main関数内で配列宣言された配列newhairetuの配列変数


newhairetu[0]

newhairetu[1]

newhairetu[2]

newhairetu[3]

newhairetu[4]


に格納されている数値データに5を加える


自作関数


void newmadefunction(int hairetu[]){


*hairetu=*hairetu+5;

*(hairetu+1)=*(hairetu+1)+5;

*(hairetu+2)=*(hairetu+2)+5;

*(hairetu+3)=*(hairetu+3)+5;

*(hairetu+4)=*(hairetu+4)+5;


}

を定義し


🐣  🐣  🐣

ここで


hairetuはhairetu[0]のアドレスを格納しているポインタ変数

hairetu+1はhairetu[1]のアドレスを格納しているポインタ変数

hairetu+2はhairetu[2]のアドレスを格納しているポインタ変数

hairetu+3はhairetu[3]のアドレスを格納しているポインタ変数

hairetu+4はhairetu[4]のアドレスを格納しているポインタ変数


なので


*hairetu

*(hairetu+1)

*(hairetu+2)

*(hairetu+3)

*(hairetu+4)


それぞれ

hairetu[0]のアドレスの場所のメモリに格納されている数値データ

hairetu[1]のアドレスの場所のメモリに格納されている数値データ

hairetu[2]のアドレスの場所のメモリに格納されている数値データ

hairetu[3]のアドレスの場所のメモリに格納されている数値データ

hairetu[4]のアドレスの場所のメモリに格納されている数値データ




すなわち


hairetu[0]に格納されている数値データ

hairetu[1]に格納されている数値データ

hairetu[2]に格納されている数値データ

hairetu[3]に格納されている数値データ

hairetu[4]に格納されている数値データ



をあらわしており


*hairetu=*hairetu+5;

*(hairetu+1)=*(hairetu+1)+5;

*(hairetu+2)=*(hairetu+2)+5;

*(hairetu+3)=*(hairetu+3)+5;

*(hairetu+4)=*(hairetu+4)+5;


が実行されると


hairetu[0]のアドレスの場所のメモリに格納されている数値データ

hairetu[1]のアドレスの場所のメモリに格納されている数値データ

hairetu[2]のアドレスの場所のメモリに格納されている数値データ

hairetu[3]のアドレスの場所のメモリに格納されている数値データ

hairetu[4]のアドレスの場所のメモリに格納されている数値データ

に5が加えられます。


🐤  🐤  🐤




main関数内で配列宣言された


配列newhairetuのアドレスを格納したポインタ変数


newhairetuを


自作関数newmadefunction(int hairetu[])の


引数であるint hairetu[] に代入して。


その状態で自作関数


newmadefunction(newhairetu);


を実行すると


main関数内で配列宣言された配列newhairetuの配列変数


newhairetu[0]

newhairetu[1]

newhairetu[2]

newhairetu[3]

newhairetu[4]


に格納されている数値データに5は加えられるのでしょうか?


プログラムを構成し


コンパイルしてみます。


どうなるかな?」


ソーラー「はいっ😊 先生」


アレサ「はいっ😊ソーラーさん」


ソーラー「はいっ😊 


もうここらあたりめっちゃめっちゃ


もうこれでもか というくらいまちがえました」


アレサ「それは・・・秘密ですの・・」




#include <stdio.h>


void newmadefunction(int hairetu[]){

*hairetu=*hairetu+5;

*(hairetu+1)=*(hairetu+1)+5;

*(hairetu+2)=*(hairetu+2)+5;

*(hairetu+3)=*(hairetu+3)+5;

*(hairetu+4)=*(hairetu+4)+5;

}


int main (void){

int newhairetu[5]={1,2,3,4,5};



printf("%d\n", newhairetu[0]);

printf("%d\n", newhairetu[1]);

printf("%d\n", newhairetu[2]);

printf("%d\n", newhairetu[3]);

printf("%d\n", newhairetu[4]);


newmadefunction(newhairetu);


printf("%d\n", newhairetu[0]);

printf("%d\n", newhairetu[1]);

printf("%d\n", newhairetu[2]);

printf("%d\n", newhairetu[3]);

printf("%d\n", newhairetu[4]);


return 0;

}


コンパイル結果

1

2

3

4

5

6

7

8

9

10


ソーラー「きれいなコンパイル結果がでてきたね。アレサ。」


アレサ「ほんとです とってもきれいですね。」


ソーラー「このコンパイル結果をみたら元気がでてきちゃったよ」


アレサ

「それではっ😊


このプログラムの流れを詳しく見ていきます😊


main関数内でint newhairetu[5]={1,2,3,4,5};


とnewhairetuの配列宣言を行ったので


配列newhairetu内には


配列変数

newhairetu[0]

newhairetu[1]

newhairetu[2]

newhairetu[3]

newhairetu[4]


が生成されて


newhairetu[0]=1;

newhairetu[1]=2;

newhairetu[2]=3;

newhairetu[3]=4;

newhairetu[4]=5;


と数値データが格納されています


自作関数

newmadefunction(newhairetu);

を実行するとき


自作関数の引数である


int hairetu[]に(によって生成されるポインタ変数hairetuに)


配列newhairetuのアドレスを格納している


ポインタ変数newhairetuを代入されます


そのとき



newhairetu[0]

newhairetu[1]

newhairetu[2]

newhairetu[3]

newhairetu[4]


のアドレスを格納しているポインタ変数


newhairetu

newhairetu+1

newhairetu+2

newhairetu+3

newhairetu+4



hairetu

hairetu+1

hairetu+2

hairetu+3

hairetu+4


というポインタ変数に格納されます


すると


newhairetu

newhairetu+1

newhairetu+2

newhairetu+3

newhairetu+4



hairetu

hairetu+1

hairetu+2

hairetu+3

hairetu+4


には


同じ


newhairetu[0]

newhairetu[1]

newhairetu[2]

newhairetu[3]

newhairetu[4]


のアドレスが格納されることになります


ですので


*hairetu

*(hairetu+1)

*(hairetu+2)

*(hairetu+3)

*(hairetu+4)


newhairetu[0]

newhairetu[1]

newhairetu[2]

newhairetu[3]

newhairetu[4]


に格納されている数値データをあらわすことになります。


そして


自作関数の操作


*hairetu=*hairetu+5;

*(hairetu+1)=*(hairetu+1)+5;

*(hairetu+2)=*(hairetu+2)+5;

*(hairetu+3)=*(hairetu+3)+5;

*(hairetu+4)=*(hairetu+4)+5;


を行うと


newhairetu[0]=newhairetu[0]+5;

newhairetu[1]=newhairetu[1]+5;

newhairetu[2]=newhairetu[2]+5;

newhairetu[3]=newhairetu[3]+5;

newhairetu[4]=newhairetu[4]+5;


が実行されることになり


newhairetu[0]

newhairetu[1]

newhairetu[2]

newhairetu[3]

newhairetu[4]


に格納されている数値データに5が加えられます


すなわち


main関数内で配列宣言された配列newhairetuの配列変数に


格納されている数値データは


自作関数の操作をうけて


5が加えられます


その結果


printf("%d\n", newhairetu[0]);

printf("%d\n", newhairetu[1]);

printf("%d\n", newhairetu[2]);

printf("%d\n", newhairetu[3]);

printf("%d\n", newhairetu[4]);


が実行されると


6

7

8

9

10



コマンドプロンプト画面にprintf出力表示されます


つまり,


このプログラムでは


自作関数の引数である


int hairetu[]に

(int hairetu[]によって作成されたポインタ変数hairetuに)



🍎配列newhairetuのアドレスを格納しているポインタ変数newhairetu🍎



を代入することにより



つまり      🍎参照渡し(ポインタ渡し)🍎



することにより

 

main関数内で配列宣言された


配列newhairetuの中の配列変数


newhairetu[0]

newhairetu[1]

newhairetu[2]

newhairetu[3]

newhairetu[4]


に格納されている数値データ


1

2

3

4

5


5を足すという自作関数の操作を加えて


配列newhairetuの中の配列変数


newhairetu[0]

newhairetu[1]

newhairetu[2]

newhairetu[3]

newhairetu[4]


に格納されている数値データを


10


変更しているのですね。   



このプログラムの例のように


自作関数の引数int hairetu[]に(int hairetu[]によって作成されるポインタ変数hairetuに)


main関数で配列宣言された配列newhairetuのアドレスを格納している


ポインタ変数newhairetuを渡す


参照渡し(ポインタ渡し)が行われていますが


実は


自作関数の引数となっている(int hairetu[]や引数int *hairetu[]によって生成される)ポインタ変数に


配列のアドレスを格納しているポインタ変数を渡す


という


この参照渡し(ポインタ渡し)の方法しか


配列のデータを自作関数の引数に渡す方法がないので


自然と


main関数内で配列宣言された配列内の配列変数の格納している数値データは


自作関数の操作を受けることになるんです」


ソーラー「一般的におこなわれている


main関数で配列宣言された配列newhairetuの配列変数に


格納されている数値データを変更するときの


自作関数の定義の記述の仕方は


void newmadefunction(int hairetu[]){

*hairetu=*hairetu+5;

*(hairetu+1)=*(hairetu+1)+5;

*(hairetu+2)=*(hairetu+2)+5;

*(hairetu+3)=*(hairetu+3)+5;

*(hairetu+4)=*(hairetu+4)+5;

}


でなく


void newmadefunction(int hairetu[]){

hairetu[0]=hairetu[0]+5;

hairetu[1]=hairetu[1]+5;

hairetu[2]=hairetu[2]+5;

hairetu[3]=hairetu[3]+5;

hairetu[4]=hairetu[4]+5;

}



これを用いたプログラムは次のようになります。


#include <stdio.h>


void newmadefunction(int hairetu[]){

hairetu[0]=hairetu[0]+5;

hairetu[1]=hairetu[1]+5;

hairetu[2]=hairetu[2]+5;

hairetu[3]=hairetu[3]+5;

hairetu[4]=hairetu[4]+5;

}


int main (void){

int newhairetu[5]={1,2,3,4,5};


printf("%d\n", newhairetu[0]);

printf("%d\n", newhairetu[1]);

printf("%d\n", newhairetu[2]);

printf("%d\n", newhairetu[3]);

printf("%d\n", newhairetu[4]);


newmadefunction(newhairetu);


printf("%d\n", newhairetu[0]);

printf("%d\n", newhairetu[1]);

printf("%d\n", newhairetu[2]);

printf("%d\n", newhairetu[3]);

printf("%d\n", newhairetu[4]);


return 0;

}


コンパイル結果


1

2

3

4

5

6

7

8

9

10


ソーラー「


void newmadefunction(int hairetu[]){

hairetu[0]=hairetu[0]+5;

hairetu[1]=hairetu[1]+5;

hairetu[2]=hairetu[2]+5;

hairetu[3]=hairetu[3]+5;

hairetu[4]=hairetu[4]+5;

}

と記述されていても

void newmadefunction(int hairetu[]){

*hairetu=*hairetu+5;

*(hairetu+1)=*(hairetu+1)+5;

*(hairetu+2)=*(hairetu+2)+5;

*(hairetu+3)=*(hairetu+3)+5;

*(hairetu+4)=*(hairetu+4)+5;

}


が記述されているのと


かわりがありませんね。



      🌞 🌞 🌞 🌞 🌞 🌞          


なぜ このように表記が変更できるのかは


   以前のエピソードでも語られましたが


後のエピソードで語られることになります。



お楽しみに!


      🌞 🌞 🌞 🌞 🌞 🌞          

 


このときも


配列newhairetuのアドレスを格納しているポインタ変数


newhairetuが


int hairetu[]に代入される


参照渡し(ポインタ渡し)となっていて


配列newhairetuの配列変数に格納されている数値データは


自作関数の操作を受けて


変化してるんだね。」


ソーラー「それにしても


プログラムを組んで実行して


きれいなコンパイル結果が出てきたね


配列のアドレスを格納しているポインタ変数newhairetuを渡すしか


配列newhairetuのデータを自作関数の引数に渡す方法がない・・・



なんとか



          値渡しはできないのかな?


と思われる方もおられると思います」


アレサ「そうですね😊」


ソーラー「それは、ぼっくん なんだよ」


アレサ「はいっ(*^▽^*)」


ソーラー「そこで


ためしに


値渡しできるかどうか確かめるために


次のプログラムのように


値渡しの方法である


自作関数の引数にmain関数内で作製された変数を直接代入する方法


つまり


自作関数の引数のint hairetu[]に


ポインタ変数newhairetuをわたさず


できるかどうかはわからないけど


直接


int hairetu[]に


newhairetu[]を代入してみます。


次のプログラムでは


main関数内で配列宣言された配列newhairetuの


配列変数


newhairetu[0]

newhairetu[1]

newhairetu[2]

newhairetu[3]

newhairetu[4]


に格納されている数値データ

1

2

3

4

5

に自作関数の操作をくわえて


6

7

8

9

10


にしようとしています


#include <stdio.h>


void newmadefunction(int hairetu[]){

hairetu[0]=hairetu[0]+5;

hairetu[1]=hairetu[1]+5;

hairetu[2]=hairetu[2]+5;

hairetu[3]=hairetu[3]+5;

hairetu[4]=hairetu[4]+5;

}

/* ここでは値渡しが行われるようにポインタ変数newhairetuを自作関数の引数にわたさないので


*hairetu=*hairetu+5;

*(hairetu+1)=*(hairetu+1)+5;

*(hairetu+2)=*(hairetu+2)+5;

*(hairetu+3)=*(hairetu+3)+5;

*(hairetu+4)=*(hairetu+4)+5;

のように

*hairetu

*(hairetu+1)

*(hairetu+2)

*(hairetu+3)

*(hairetu+4)

を使わず

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

をもちいて自作関数の定義をおこなっています*/


int main (void){

int newhairetu[5]={1,2,3,4,5};

printf("%d\n", newhairetu[0]);

newmadefunction(newhairetu[]);

/*ここで 自作関数の引数であるint hairetu[]に

ポインタ変数newhairetuの代わりに

newhairetu[]を代入しています*/


printf("%d\n",newhairetu[0]);

printf("%d\n",newhairetu[1]);

printf("%d\n",newhairetu[2]);

printf("%d\n",newhairetu[3]);

printf("%d\n",newhairetu[4]);

return 0;

}


コンパイル結果


EAZY IDECの場合

ファイル「C:/Users/solarplexuss/AppData/Local/EasyIDEC/project/solarplexuss/main.c」の

「34行目」で記述エラーを発見しました。

「identifier」を付け忘れています。



Visual Studioの場合

エラー C2059 構文エラー: ']'

エラー (アクティブ) E0029 式が必要です



ソーラー「このように


コンパイル結果はエラーがでてしまい


コンパイルできません


値渡しはできないことがわかります


ははあ・・・


さては・・・


なぁ~るほど(´▽`*)


C言語の作者さんは


値渡しはやめてポインタ渡しだけにしたほうがベストとおもったのかな?」


アレサ「そうですね。ここらあたりに開発者さんの考えが


うかがえるとおもいますの。」


ソーラー「


自作関数の定義が

👇

void newmadefunction(int hairetu[]){

hairetu[0]=hairetu[0]+5;

hairetu[1]=hairetu[1]+5;

hairetu[2]=hairetu[2]+5;

hairetu[3]=hairetu[3]+5;

hairetu[4]=hairetu[4]+5;

}



引数部分が


int hairetu[]


となっている・・・か・・・


もしかして


引数部分が


int hairetu[]


になってるのは


int hairetu[3]


int hairetu[5]


のように


要素数を固定して


決めることができないからなんじゃないかな?」


アレサ「あっ そうですの」





  • Xで共有
  • Facebookで共有
  • はてなブックマークでブックマーク

作者を応援しよう!

ハートをクリックで、簡単に応援の気持ちを伝えられます。(ログインが必要です)

応援したユーザー

応援すると応援コメントも書けます

新規登録で充実の読書を

マイページ
読書の状況から作品を自動で分類して簡単に管理できる
小説の未読話数がひと目でわかり前回の続きから読める
フォローしたユーザーの活動を追える
通知
小説の更新や作者の新作の情報を受け取れる
閲覧履歴
以前読んだ小説が一覧で見つけやすい
新規ユーザー登録無料

アカウントをお持ちの方はログイン

カクヨムで可能な読書体験をくわしく知る