自作関数の引数にポインタ変数宣言や配列宣言をつかって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 *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関数内で定義された配列を


代入するプログラムは


次のように記述していました。


#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[]が干しイカににているのは


だいたい覚えてる」


アレサ「素敵です


このプログラムは


自作関数内の引数( )内に


int hairetu[]に代わり


ポインタ変数宣言


int *hairetu


を用いて


書き換えることができます。」


ソーラー「int *hairetuなんだね」


アレサ「では、プログラムを


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]

がアクセスしている


メモリのアドレスにアクセスできるようになります。


すなわち

配列変数

newhairetu[0]

newhairetu[1]

newhairetu[2]

newhairetu[3]

newhairetu[4]

配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[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によって生成された


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]



int *hairetuによって作製されるポインタ変数hairetuに


配列newhairetuのアドレスを持つ


ポインタ変数newhairetuが代入されると


*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)

は     

配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


と等しいのは前のエピソードでもやったかな?


根本的に


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


  🐤🐤🐤🐤🐤🐤🐤🐤今🐤🐤🐤🐤🐤🐤🐤🐤


配列hairetuのポインタ変数hairetuに格納されているアドレス💖💖💖💖💖💖💖💖💖💖💖💖💖💖のメモリにアクセスする窓であり


そのメモリに格納されている数値をあらわすのでした。


だから


配列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[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


が作製されます。


そして


配列 newhairetuのアドレスをもつポインタ変数newhairetuが


自作関数内で


ポインタ変数宣言

int *hairetu


により作成された


ポインタ変数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[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

が作製されて


ポインタ変数newhairetuが


void newmadefunction(int *hairetu)


の引数であるint *hairetuに代入され


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とポインタ変数宣言をおこなって


配列newhairetuの配列変数のアドレスnewhairetuを


ポインタ変数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]

はデータにアクセスするための窓の役割をはたしています。


だから

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

ポインタ変数newhairetuに別のメモリのアドレスが与えられると


newhairetu[0]

newhairetu[1]

newhairetu[2]

newhairetu[3]

newhairetu[4]


別のメモリにアクセスする窓となり


別のメモリに格納されている数値データをあらわすことになるんだね。


🍋  🍋  🍋  🍋  🍋  🍋  🍋  🍋  🍋



ですが


自作関数の引数で配列宣言された配列のアドレスを格納しているポインタ変数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[0]

newhairetu[1]

newhairetu[2]

newhairetu[3]

newhairetu[4]

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



1

2

3

4

5

から

6

7

8

9

10



変更することはできません。


🍋  🍋  🍋  🍋  🍋  🍋  🍋  🍋  🍋



ソーラー「


もう1度


最初から


ポインタ変数宣言int *hairetuを用いて


main関数内で定義された配列newhairetuに格納された数値データを


自作関数のnewmadefunctionの引数にわたす


プログラムをみてみるかな?」


#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[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のアドレスを与えられることにより


*ptaが変数bのアドレスに格納されている数値をあらわすことに


なることに相当しているんです、ね


solarplexussさん」




solarplexuss「


この説明を・・・ 


待って


    待って 


        待って


待ちつづけていたんだよぉおぉぉお」


ソーラー「やったね!」

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

作者を応援しよう!

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

応援したユーザー

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