天国にいけるC言語入門 ヘキサ構造体 ver5.2130
配列宣言を自作関数の引数に設定し自作関数の実行時main関数内で定義された配列のアドレスを格納したポインタ変数を代入することができます。参照渡し(ポインタ渡し)となり値渡しされる方法はありません
👆このことは ゲームキャラクターが移動することやゲームキャラの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]
に格納されている数値データを
6
7
8
9
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]
のように
要素数を固定して
決めることができないからなんじゃないかな?」
アレサ「あっ そうですの」
新規登録で充実の読書を
- マイページ
- 読書の状況から作品を自動で分類して簡単に管理できる
- 小説の未読話数がひと目でわかり前回の続きから読める
- フォローしたユーザーの活動を追える
- 通知
- 小説の更新や作者の新作の情報を受け取れる
- 閲覧履歴
- 以前読んだ小説が一覧で見つけやすい
アカウントをお持ちの方はログイン
ビューワー設定
文字サイズ
背景色
フォント
組み方向
機能をオンにすると、画面の下部をタップする度に自動的にスクロールして読み進められます。
応援すると応援コメントも書けます