天国にいけるC言語入門 ヘキサ構造体 ver5.2130
自作関数の引数となっているポインタ変数宣言や配列宣言にmain関数内で作成された配列のアドレスを格納しているポインタ変数を参照渡し(ポインタ渡し)することができます
自作関数の引数となっているポインタ変数宣言や配列宣言にmain関数内で作成された配列のアドレスを格納しているポインタ変数を参照渡し(ポインタ渡し)することができます
ソーラー「
複数の数値データ1,2,3,4,5があるとするね
1つのポインタ変数宣言をつかって
その数値データ1,2,3,4,5を一度にメモリに格納できるよう
int* hairetu={1,2,3,4,5};
や
int* hairetu[]={1,2,3,4,5};
が
機能するよう
C言語をつくっておけばよかったんだけど・・・
1つのポインタ変数宣言をつかって
複数の数値データを1度にメモリに格納する方法をC言語の開発者は
つくらなかったのか・・・
(つくらなかったというよりは もともとint*型の変数はポインタ変数なのでアドレスしか格納することはできないので 作るのは無理💖といったほうが良いと思います)
int* hairetu
や
int* hairetu[]
によって生成される
hairetu[0]
hairetu[1]
hairetu[2]
・
・
・
は
int*型に格納されているアドレスなら格納できるというわけなんだね
🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞
実際に
ポインタ変数宣言
int* hairetu={1,2,3,4,5};
をつかった
次のプログラム
#include <stdio.h>
int main (void){
int* hairetu={1,2,3,4,5}
for(i=0;i<5;i++)
printf("%d\n",hairetu[i]);
return 0;
}
は、コンパイルエラーがでて
int* hairetu={1,2,3,4,5};
は機能しないことがわかります。
int* hairetu[]を用いたプログラムも
#include <stdio.h>
int main (void){
int *hairetu[]={1,2,3,4,5}
for(i=0;i<5;i++)
printf("%d\n",hairetu[i]);
return 0;
}
コンパイルエラーがでて
int *hairetu[]={1,2,3,4,5};
は機能しないことが
わかります。
🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞
ソーラー「
しかし こうして
ポインタ変数宣言をつかって
データをメモリに格納するいろんなパターンを調べてみるのは
とてもおもしろいね。
だって
すこしづつだけど
なんとなくポインタ変数が使いこなせるような
気がしてくるからね
よし 次 いってみよ~~」
アレサ「はいっ
自作関数の引数にmain関数内で定義された配列hairetuのアドレスを格納しているポインタ変数を
代入するプログラムは
次のように記述していました。
#include <stdio.h>
void newmadefunction(int hairetu[]){
int i;
for(i=0;i<5;i++)
printf("%d\n",hairetu[i]);
}
int main (void){
int newhairetu[5]={1,2,3,4,5};
newmadefunction(newhairetu);
return 0;
}
コンパイル結果
1
2
3
4
5
アレサ「
このプログラムでは
自作関数newmadefunction内の引数( )に
次のように
void newmadefunction(int hairetu[])
int hairetu[]が記述されています。
いかがですか。
ここまでは覚えておられましたか」
ソーラー「int hairetu[]が干しイカににているのは
だいたい覚えてる」
アレサ「素敵です
このプログラムは
自作関数newmadefunction内の引数( )内に
配列宣言
int hairetu[]がつかわれていますが
😊😊int hairetu[]に代わりに😊😊
ポインタ変数宣言
😊int* hairetu😊
を用いて
書き換えることができます。」
ソーラー「int* hairetuなんだね」
アレサ「では、自作関数newmadefunction内の定義の引数部分を
int hairetu[]の代わりに
int* hairetuを使って
書き換えてみます。
👇
#include <stdio.h>
void newmadefunction(int* hairetu){
int i;
for(i=0;i<5;i++)
printf("%d\n",hairetu[i]);
}
int main (void){
int newhairetu[5]={1,2,3,4,5};
newmadefunction(newhairetu);
return 0;
}
コンパイル結果
1
2
3
4
5
アレサ「この場合
void newmadefunction(int* hairetu)の
int* hairetuに
main関数内で定義された配列newhairetuのアドレスを
格納しているポインタ変数
newhairetu
が代入されることにより
つまり
ポインタ変数
hairetuには
newhairetu
が代入されます。
いいかえると
hairetu
hairetu+1
hairetu+2
hairetu+3
hairetu+4
に
配列newhairetuの配列変数
newhairetu[0]
newhairetu[1]
newhairetu[2]
newhairetu[3]
newhairetu[4]
がアクセスしている
メモリのアドレスを格納しているポインタ変数
newhairetu
newhairetu+1
newhairetu+2
newhairetu+3
newhairetu+4
が代入されているともいえます。
すると
配列変数
hairetu[0]
hairetu[1]
hairetu[2]
hairetu[3]
hairetu[4]
は
newhairetu[0]
newhairetu[1]
newhairetu[2]
newhairetu[3]
newhairetu[4]
がアクセスしている
メモリのアドレスにアクセスできるようになります。
すなわち
配列変数
hairetu[0]
hairetu[1]
hairetu[2]
hairetu[3]
hairetu[4]
と
配列変数
newhairetu[0]
newhairetu[1]
newhairetu[2]
newhairetu[3]
newhairetu[4]
は
同じアドレスのメモリにアクセスする配列変数となっているんですの。
そして
配列変数
hairetu[0]
hairetu[1]
hairetu[2]
hairetu[3]
hairetu[4]
と
配列変数
newhairetu[0]
newhairetu[1]
newhairetu[2]
newhairetu[3]
newhairetu[4]
は
同じアドレスのメモリに
アクセスしている窓であり
同じアドレスのメモリが格納している数値データを表すことができます
また
配列変数
hairetu[0]
hairetu[1]
hairetu[2]
hairetu[3]
hairetu[4]
と
配列変数
newhairetu[0]
newhairetu[1]
newhairetu[2]
newhairetu[3]
newhairetu[4]
は
同じアドレスのメモリに格納されている数値データを変更することができます
操作することができます。
今の状況を別のたとえでたとえるなら
変数aのアドレスがポインタ変数ptaに格納されていると
*ptaは変数aのアドレスのメモリに格納されている数値データに
アクセスすることができるようになります
この
ポインタ変数pta
が
ポインタ変数ptb
に
ptb=pta;
のように代入されると
ともに
変数aのアドレスが与えられたポインタ変数
pta
ptb
となり
*ptbは変数aのアドレスのメモリに格納されている数値データに
アクセスすることができるようになります。
このことは
ポインタ変数newhairetuがポインタ変数hairetuに代入されることに
相当します。
ポインタ変数newhairetuがポインタ変数hairetuに代入されると
配列変数
newhairetu[0]
newhairetu[1]
newhairetu[2]
newhairetu[3]
newhairetu[4]
と
配列変数
hairetu[0]
hairetu[1]
hairetu[2]
hairetu[3]
hairetu[4]
は
同じアドレスのメモリにアクセスする配列変数となります。
ptaがポインタ変数newhairetu
ptbがポインタ変数hairetu
*ptaが
配列変数
newhairetu[0]
newhairetu[1]
newhairetu[2]
newhairetu[3]
newhairetu[4]
*ptbが
配列変数
hairetu[0]
hairetu[1]
hairetu[2]
hairetu[3]
hairetu[4]
に相当するというわけですね。
ソーラーさん」
ソーラー「これは・・・( ̄ー ̄)ニヤリ
🍓1つのポインタ変数宣言をつかって🍓
🍓複数の数値データ(この場合1,2,3,4,5)をメモリに1度に取り込む方法はない🍓
のだけど
この例もそうだということだね。
だって
あるアドレスのメモリに格納されている数値データを
newhairetu[0]
newhairetu[1]
newhairetu[2]
newhairetu[3]
newhairetu[4]
を通して
アクセスするか
hairetu[0]
hairetu[1]
hairetu[2]
hairetu[3]
hairetu[4]
を通してアクセスしているか
というだけのことだからね。
あらたに
自作関数の引数に
1つのポインタ変数宣言int* hairetuをつかって
複数の数値データ(この場合1,2,3,4,5)を
他のメモリに新たに1度に取り込んだわけではなく
もともとメモリに格納されている数値データに
他の方法
つまり
配列変数
hairetu[0]
hairetu[1]
hairetu[2]
hairetu[3]
hairetu[4]
を使ってアクセスしただけのことなんだね。
だから
1つのポインタ変数宣言int* hairetuをつかって
ゼロから新たに
複数の数値データ(この場合1,2,3,4,5)をメモリに格納したとは言えないね。」
solarplexuss「わかったかもん!」
ソーラー「さらに別の言い方だと
参照渡し(ポインタ渡し)とは
例えば
main関数内で定義された
変数aのアドレスを格納したポインタ変数を
自作関数の引数であるポインタ変数に代入して
変数のアドレスを渡すことでした。
そして変数aのアドレスが格納されたポインタ変数を操作することにより
変数aのアドレスのメモリに格納されている数値データを変更することができました。
ということは
最初から変数aのア|ドレスのメモリにだけ数値データは格納されていて《💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖》
ポインタ変数をつかって
変数aのアドレスのメモリに格納されている数値データの値を
変更しただけなのです。
ポインタ変数宣言をおこなったことにより
新たな変数が別にメモリ上に作製され
そこに数値データが格納されたわけではありません。」
solarplexuss「おおぉぉ・・よくわからんけど・・なんかいい・・」
ソーラー「
ポインタ変数宣言int* ptaをおこなって
作製されたポインタ変数ptaに変数aのアドレス&aを
pta=&a;
と
代入すれば
*ptaは変数aのもつ数値データを格納することになりますが
それは
変数aとは違う*ptaという変数が新たにメモリ上に作製され
そのメモリに
変数aのもつ数値データが格納されているわけではないってことだよね。
*ptaは変数aのアドレスを持つメモリにアクセスして
変数aのもつ数値データを表すことになったのだから
変数aのもつ数値データを格納しているのは
変数aのアドレスを持つメモリだけということになるんだね。」
solarplexuss「う~んいいね。
そこを もうひとおしして説明してもらえると・・」
ソーラー「そっか
じゃあ
別の説明をこころみてみるよ
自作関数
void newmadefunction(int* hairetu)の引数である
ポインタ変数宣言int* hairetuに
配列newhairetuのアドレスを持つ
ポインタ変数newhairetuが代入されると
hairetuに[]演算子を作用させた
配列変数
hairetu[0]
hairetu[1]
hairetu[2]
hairetu[3]
hairetu[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
にアスタリスク演算子を作用させた
*hairetu
*(hairetu+1)
*(hairetu+2)
*(hairetu+3)
*(hairetu+4)
は
*newhairetu
*(newhairetu+1)
*(newhairetu+2)
*(newhairetu+3)
*(newhairetu+4)
をあらわすことになり
*newhairetu
*(newhairetu+1)
*(newhairetu+2)
*(newhairetu+3)
*(newhairetu+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[0]
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)
は
配列変数
hairetu[0]
hairetu[1]
hairetu[2]
hairetu[3]
hairetu[4]
と等しいのは前のエピソードでもやったかな?
根本的に
配列変数
hairetu[0]
hairetu[1]
hairetu[2]
hairetu[3]
hairetu[4]
は
🐤🐤🐤🐤🐤🐤🐤🐤今🐤🐤🐤🐤🐤🐤🐤🐤
配列hairetuのポインタ変
(
hairetu
hairetu+1
hairetu+2
hairetu+3
hairetu+4
に格納されているアドレスのメモリにアクセスする窓であり)
そのメモリに格納されている数値データをあらわすのでした。
だから
配列hairetuのポインタ変数hairetuに
配列newhairetuのアドレスを格納しているポインタ変数newhairetuが
代入されると
配列変数
hairetu[0]
hairetu[1]
hairetu[2]
hairetu[3]
hairetu[4]
は
newhairetu[0]
newhairetu[1]
newhairetu[2]
newhairetu[3]
newhairetu[4]
と同じアドレスのメモリに格納されている数値データを
格納することになります。
newhairetu[0]
newhairetu[1]
newhairetu[2]
newhairetu[3]
newhairetu[4]
と
hairetu[0]
hairetu[1]
hairetu[2]
hairetu[3]
hairetu[4]
は
同じメモリにアクセスしている窓であり
そのメモリが格納している数値データを格納しているんだね。」
solarplexuss「おおぉぉ・・なんかいい」
ソーラー「よ、よ~し
だから
まずmain関数内で
newhairetuの配列宣言
int newhairetu[5]={1,2,3,4,5};
が実行されると
あるメモリに
1
2
3
4
5
が格納されます.
次に
自作関数の引数部分内で
int* hairetu
と
ポインタ変数宣言がおこなわれ
ポインタ変数hairetuが生成され
配列newhairetuのアドレスをもつポインタ変数newhairetuが
ポインタ変数hairetuに代入されると
配列変数
hairetu[0]
hairetu[1]
hairetu[2]
hairetu[3]
hairetu[4]
は
今
配列hairetuのポインタ変数hairetuに格納されているアドレスのメモリに
アクセスする窓であり
そのメモリに格納されている数値データをあらわすので
今
配列hairetuのポインタ変数hairetuに格納されているのは
ポインタ変数newhairetuであり
ポインタ変数newhairetuは
配列newhairetuのアドレスを格納しているので
配列変数
hairetu[0]
hairetu[1]
hairetu[2]
hairetu[3]
hairetu[4]
は
配列newhairetuのアドレスを持つメモリを先頭とするメモリ領域にアクセスし
そのメモリ領域に格納されている数値データをあらわすことになります。
このとき
配列newhairetuのアドレスを持つメモリを先頭とするメモリ領域は
1
2
3
4
5
を格納しているので
配列変数
hairetu[0]
hairetu[1]
hairetu[2]
hairetu[3]
hairetu[4]
は
1
2
3
4
5
を格納することになります。
なので
newhairetu[0]
newhairetu[1]
newhairetu[2]
newhairetu[3]
newhairetu[4]
と
hairetu[0]
hairetu[1]
hairetu[2]
hairetu[3]
hairetu[4]
は
同時に同じメモリにアクセスして
そのメモリに格納されている数値データを表しているというわけなんだ。
だから
もともと
あるメモリには
数値データ
1
2
3
4
5
が格納されているのはまちがいないんだけど
自作関数内で
void newmadefunction(int* hairetu)と
ポインタ変数宣言
int* hairetuがおこなわれて
生成されたポインタ変数hairetuに
ポインタ変数newhairetuが代入されると
hairetu[0]
hairetu[1]
hairetu[2]
hairetu[3]
hairetu[4]
が
数値データ
1
2
3
4
5
を
格納することになったとしても
それは
あらたに別のメモリに
1
2
3
4
5
を
格納したことにはならないんだ。
もとから存在する
あるメモリに
数値データ
1
2
3
4
5
は格納されていて
ポインタ変数newhairetuがポインタ変数hairetuに代入されることにより
もとから存在する
あるメモリに
配列変数
hairetu[0]
hairetu[1]
hairetu[2]
hairetu[3]
hairetu[4]
は
アクセスする窓となり
あるメモリに格納されている
数値データ
1
2
3
4
5
をあらわすことになっただけなんだね。
配列変数
hairetu[0]
hairetu[1]
hairetu[2]
hairetu[3]
hairetu[4]
という
変数がメモリに作製され
あらたにそのメモリに
数値データ
1
2
3
4
5
が格納されたわけではないんだね。
どう?みんなの注目 僕にあつまったかな?」
アレサ「はいっ ソーラーさん😊」
solarplexuss「いい~~~~
もう1ど、もう1どぉぉぉ
その・・
説明をお願いしたいのです。」
ソーラー「もう、まかしてよ~~~
COME ON!!!
自作関数の引数として
int* hairetuと
hairetuのポインタ変数宣言をおこなって
配列newhairetuのアドレスnewhairetuを
ポインタ変数hairetuに代入すると
hairetuに[]演算子を用いた
配列変数
hairetu[0]
hairetu[1]
hairetu[2]
hairetu[3]
hairetu[4]
は
配列newhairetuの配列変数
newhairetu[0]
newhairetu[1]
newhairetu[2]
newhairetu[3]
newhairetu[4]
がアクセスしているメモリ
にアクセスすることになり
数値データ
1
2
3
4
5
を表すことになるのがポイントかな?
配列newhairetuの配列変数
newhairetu[0]
newhairetu[1]
newhairetu[2]
newhairetu[3]
newhairetu[4]
も
メモリに格納されている数値データ
1
2
3
4
5
にアクセスする窓であり
そのメモリに格納されている数値データ
1
2
3
4
5
をあらわしているんだね。
ちょっとおまけ
配列宣言、初期化
int newhairetu[5]={1,2,3,4,5};
の代わりに
配列宣言
int newhairetu[5];
を実行し
int newhairetu[5];
により作製された
配列変数
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;
のように
代入したとします。
生成された配列変数
newhairetu[0]
newhairetu[1]
newhairetu[2]
newhairetu[3]
newhairetu[4]
を通して
数値データ
1
2
3
4
5
はあるメモリに格納されています。
この場合も
newhairetu[0]
newhairetu[1]
newhairetu[2]
newhairetu[3]
newhairetu[4]
はデータにアクセスするための窓の役割をはたしています。
🍋 🍋 🍋 🍋 🍋 🍋 🍋 🍋 🍋
ところで
💖自作関数の引数部分で💖
int* hairetu
と
配列宣言された配列hairetuのアドレスを格納しているポインタ変数hairetuに
main関数内で
配列宣言された配列newhairetuのアドレスを格納したポインタ変数newhairetuを代入することはできますが
🍋main関数内で🍋
配列宣言された配列newhairetuのアドレスを格納したポインタ変数newhairetuに
main関数内で
配列宣言された配列newhairetu2のアドレスを格納したポインタ変数newhairetu2を代入することはできません。
ですので
main関数内の配列宣言
int newhairetu[5]={1,2,3,4,5};
によって
配列変数
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;
のように
が代入された場合
main関数内で
配列宣言された配列newhairetuのアドレスを格納したポインタ変数newhairetuに
main関数内で
int newhairetu2[5]={6,7,8,9,10};
と
配列宣言された配列newhairetu2のアドレスを格納したポインタ変数newhairetu2を
newhairetu=newhairetu2;
と代入して
配列変数
newhairetu[0]
newhairetu[1]
newhairetu[2]
newhairetu[3]
newhairetu[4]
に
格納されている数値データ
を
1
2
3
4
5
から
6
7
8
9
10
と
変更することはできません。
🍋 🍋 🍋 🍋 🍋 🍋 🍋 🍋 🍋
ソーラー「
もう1度
自作関数newmadefunctionの引数となっている
ポインタ変数宣言int* hairetuによって作製された
ポインタ変数hairetuに
main関数内で配列宣言された配列newhairetuのアドレスを格納している
ポインタ変数newhairetuが代入されると
配列変数
hairetu[0]
hairetu[1]
hairetu[2]
hairetu[3]
hairetu[4]
は
ポインタ変数newhairetuが格納しているアドレスのメモリ
つまり
配列newhairetuの配列変数
newhairetu[0]
newhairetu[1]
newhairetu[2]
newhairetu[3]
newhairetu[4]
がアクセスしているメモリ
に
アクセスする窓になり
配列newhairetuの配列変数
newhairetu[0]
newhairetu[1]
newhairetu[2]
newhairetu[3]
newhairetu[4]
がアクセスしているメモリ
に
格納されている数値データ
を表すことになる
プログラムをみてみるかな?」
#include <stdio.h>
void newmadefunction(int* hairetu){
int i;
for(i=0;i<5;i++)
printf("%d\n",hairetu[i]);
}
int main (void){
int newhairetu[5]={1,2,3,4,5};
newmadefunction(newhairetu);
return 0;
}
コンパイル結果
1
2
3
4
5
ソーラー「
配列newhairetuのアドレスを格納しているポインタ変数newhairetu
が
ポインタ変数宣言int* hairetuによって
作製されるポインタ変数hairetu
に代入されることにより
hairetuに[]演算子を用いて作製された配列変数
hairetu[0]
hairetu[1]
hairetu[2]
hairetu[3]
hairetu[4]
は
配列newhairetuの配列変数
newhairetu[0]
newhairetu[1]
newhairetu[2]
newhairetu[3]
newhairetu[4]
のアクセスしているメモリの格納しているデータを
あらわすことになります。
このことは
ポインタ変数ptaに変数bのアドレスを
pta=&b;
のように
代入すると
*ptaは変数bの格納している値をあらわすことになる関係と
一緒です。
ポインタ変数ptaはポインタ変数hairetuに相当し
変数bのアドレス&bは配列newhairetuのアドレスを格納している
ポインタ変数newhairetuに相当します。
配列変数
hairetu[0]
hairetu[1]
hairetu[2]
hairetu[3]
hairetu[4]
は
*pta
に相当します。
自作関数の引数となっている配列hairetuのアドレスを格納している
ポインタ変数hairetuに
main関数内で定義された配列newhairetuのアドレスを格納している
ポインタ変数newhairetuが代入されるということは
pta=&b;
に相当します。
自作関数の引数となっているint* hairetuによって作製された
ポインタ変数hairetuに
main関数内で配列宣言された配列newhairetuのアドレスを格納している
ポインタ変数newhairetuが代入されると
配列変数
hairetu[0]
hairetu[1]
hairetu[2]
hairetu[3]
hairetu[4]
は
ポインタ変数newhairetuが格納しているアドレスのメモリ
つまり
配列newhairetuの配列変数
newhairetu[0]
newhairetu[1]
newhairetu[2]
newhairetu[3]
newhairetu[4]
がアクセスしているメモリ
に
アクセスする窓になり
配列newhairetuの配列変数
newhairetu[0]
newhairetu[1]
newhairetu[2]
newhairetu[3]
newhairetu[4]
が
アクセスしているメモリに
格納されている数値データ
1
2
3
4
5
を表すことになります。
これは
ポインタ変数ptaが変数bのアドレス&bを与えられることにより
*ptaが変数bのアドレスに格納されている数値データをあらわすことに
なることに相当しているんです、ね
solarplexussさん」
solarplexuss「
この説明を・・・
待って
待って
待って
待ちつづけていたんだよぉおぉぉお」
ソーラー「やったね!」
新規登録で充実の読書を
- マイページ
- 読書の状況から作品を自動で分類して簡単に管理できる
- 小説の未読話数がひと目でわかり前回の続きから読める
- フォローしたユーザーの活動を追える
- 通知
- 小説の更新や作者の新作の情報を受け取れる
- 閲覧履歴
- 以前読んだ小説が一覧で見つけやすい
アカウントをお持ちの方はログイン
ビューワー設定
文字サイズ
背景色
フォント
組み方向
機能をオンにすると、画面の下部をタップする度に自動的にスクロールして読み進められます。
応援すると応援コメントも書けます