main関数内で定義された配列に格納されている数値を自作関数を使って変更してみましょう。自作関数の引数が(int *hairetu)となっている場合🌞

アレサ


「ここで再び配列の仕組みにもどってみますの。


#include <stdio.h>


int main (void){


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


int i;


for(i=0;i<5;i++)


printf("%d\n",hairetu[i]);


return 0;


}


コンパイル結果

1

2

3

4

5



アレサ「ここでは配列hairetuの配列変数


hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


1

2

3

4

5


の5つの数値をとりこみ

for(i=0;i<5;i++)


printf("%d\n",hairetu[i]);


の命令文により


コンパイル結果

1

2

3

4

5


を表示しています。」



ソーラー「配列宣言int hairetu[]={1,2,3,4,5};を


おこない


生成された


配列変数


hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


に数値1,2,3,4,5を


hairetu[0]=1;

hairetu[1]=2;

hairetu[2]=3;

hairetu[3]=4;

hairetu[4]=5;


と取り込んでいると


そういうわけなんだねっ くすっ」




アレサ「この配列宣言int hairetu[];


を自作関数の引数の部分に記入し


main関数内で定義された別の配列内の配列変数のアドレス情報を


自作関数の引数にポインタ渡しすることができましたね。」


ソーラー「そうだったね😊」


アレサ「


配列を引数とした自作関数を使って構成された


プログラムは次のようなものでした。」



#include <stdio.h>


void newmadefunction(int hairetu[]){


*hairetu=*hairetu*2;

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

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

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

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


}


/*int hairetu[]を自作関数の()内にかきこみました*/


int main (void){


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


newmadefunction(newhairetu);



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


ポインタ変数newhairetuが自作関数の引数として


int hairetu[]に代入されています*/



int j;


for(j=0;j<5;j++)


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


return 0;


}


コンパイル結果


2

4

6

8

10



アレサ「

このプログラムでは


冒頭の自作関数宣言で自作関数newmadefunctionの引数を


配列とするためにnewmadefunction()の()内で


配列宣言int hairetu[]をおこなっています


そしてmain関数内で


新しくつくられた配列newhairetu


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


を自作関数


newmadefunction(int hairetu[])内の引数である


int hairetu[]に代入しています・・・・・・



ここで


int hairetu[]を int *hairetuと記述して


プログラムを次のように書き換えることができます



#include <stdio.h>


void newmadefunction(int *hairetu){


*hairetu=*hairetu*2;

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

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

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

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


}


/*int *hairetuを自作関数の()内に引数としてかきこみました*/


int main (void){


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


newmadefunction(newhairetu);



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


ポインタ変数newhairetuが自作関数の引数として


ポインタ変数hairetuに代入されています。


*/



int j;


for(j=0;j<5;j++)


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


return 0;


}


コンパイル結果

EAZY IDECの場合

2

4

6

8

10


Visual Studioの場合

2

4

6

8

10


アレサ「ここで注目するべきところは


やはり


自作関数newmadefunction(int *hairetu)の


引数 int *hairetuに


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


ポインタ変数newhairetuを


代入しているところです。」



ソーラー「



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


ポインタ変数newhairetuを


自作関数の引数である


int *hairetuに


代入する???


😊😊😊

オオウ ノウ

オオ~~~~~ ノウ~~~~~~~

オオオオオオオオ ノウ~~~~~~

オオウ オオウ ノウ

オオ~~~~~ホワット? ノォノウ~~~

オオオオオオオオオオオオオオオオ ノウ~~~~~~

ノン

オオ~~~~~ ノウ~~~~~~~

オオオオオオオオ ノウ~~~~~~

オケェ~

オ~イェエ~~


オオウ ノウ

ホワァイ~


オ~


セェイ イェエ~~

オオオオウ~~~~~ ノウ~~~~~~~

ノウ~~~~~~~~~~~~~~


わんわん

オオオオオオオオオオオオオオオオ 

わたしわかりません


どういうこと?????


前のエピソードでは


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


ポインタ変数newhairetuを


自作関数の引数である


int hairetu[]に代入していたね。


ま 


それは何とか分かったんだけど・・・


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


ポインタ変数newhairetuを


自作関数の引数である


int *hairetu


に代入する???????


ポインタ変数newhairetuを

ポインタ変数hairetuに代入するということだよね???


いやぁ


確かに


ポインタ変数newhairetuを

ポインタ変数hairetuに代入する


ことは可能なんだろうけど


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


ポインタ変数newhairetuを


自作関数の引数である


int *hairetu


に代入することに


どのような意味があるのか?


というところが分からないよね。


わかるわけがないよね。」




アレサ「ここでなぜ


配列のアドレスを格納した


ポインタ変数newhairetuを自作関数の引数に代入するのに



  引数に  ポインタ変数宣言int *hairetuが行われているのか




不思議とおもわれますか。


じつは理由を聞いてしまえばとても簡単なことなんですの。」



ソーラー「え~そうなのかい?


とてもそうはみえないけど?」


アレサ「実は


[ ]演算子のエピソードでもみてきたように


自作関数の引数となっているポインタ変数宣言int *hairetuにより


配列変数


hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

hairetu[5]

をつかって


メモリにアクセスすることができるようになるのです。


まず


ポインタ変数hairetuに


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


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


どのようなことが起こるかについてですが


ここでは


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


配列newhairetu[5]の要素数5にあわせて


配列変数


hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


だけ取り出して考えてみます


ソーラー「


それはつまり


int *hairetu


配列宣言

int hairetu[5];

おこなっているということ?」


アレサ「正確には


配列宣言

int hairetu[5];


がおこなわれているわけではありませんが


配列hairetuが作製されて


配列変数


hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


が生成されていると思われても構いません。


そして


この配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


はポインタ変数でないので


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


ポインタ変数newhairetuが


ポインタ変数hairetuに代入されても


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

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

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

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

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


を格納することはできません。


格納してもいみないのですの。」



ソーラー「そう、またまたそのとおり😊\(^o^)/


やっぱり 読者のみなさんもそう思うよね」




アレサ「ですが


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


int *hairetuが行われ


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


が生成されると


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


hairetu

hairetu+1

hairetu+2

hairetu+3

hairetu+4


も同時に生成されています


つまり


自作関数の引数である()内のint *hairetuによって生成される


ポインタ変数hairetu



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


代入するということは


自作関数newmadefunction(int *hairetu)の()内の


ポインタ変数宣言


int *hairetu


によって作られることになったポインタ変数


hairetu

hairetu+1

hairetu+2

hairetu+3

hairetu+4



newhairetuの配列宣言によって作られたポインタ変数


newhairetu

newhairetu+1

newhairetu+2

newhairetu+3

newhairetu+4


を代入していることになります。」


ソーラー「なういっ!


い、いや


なっなんだってぇ~」



アレサ



このようにして


newhairetu[0]

newhairetu[1]

newhairetu[2]

newhairetu[3]

newhairetu[4]


のアドレスを


newhairetu[0]

newhairetu[1]

newhairetu[2]

newhairetu[3]

newhairetu[4]


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


newhairetu

newhairetu+1

newhairetu+2

newhairetu+3

newhairetu+4


を使って


配列hairetuのポインタ変数


hairetu

hairetu+1

hairetu+2

hairetu+3

hairetu+4


に代入すると


自作関数の定義の


*hairetu=*hairetu*2;

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

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

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

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


により


*newhairetu=*newhairetu*2;

*(newhairetu+1)=*(newhairetu+1)*2;

*(newhairetu+2)=*(newhairetu+2)*2;

*(newhairetu+3)=*(newhairetu+3)*2;

*(newhairetu+4)=*(newhairetu+4)*2;



がおこなわれることになります


*newhairetu

*(newhairetu+1)

*(newhairetu+2)

*(newhairetu+3)

*(newhairetu+4)



それぞれ


newhairetu[0]

newhairetu[1]

newhairetu[2]

newhairetu[3]

newhairetu[4]


に格納されている数値をあらわすため


*newhairetu=*newhairetu*2;

*(newhairetu+1)=*(newhairetu+1)*2;

*(newhairetu+2)=*(newhairetu+2)*2;

*(newhairetu+3)=*(newhairetu+3)*2;

*(newhairetu+4)=*(newhairetu+4)*2;


の実行により

newhairetu[0]

newhairetu[1]

newhairetu[2]

newhairetu[3]

newhairetu[4]


に格納されている数値は2倍になります。


このようにして


ポインタ変数宣言


int *hairetu


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


ポインタ変数newhairetuを渡して


newhairetu[0]

newhairetu[1]

newhairetu[2]

newhairetu[3]

newhairetu[4]


のアドレスをポインタ渡しすることにより


自作関数をつかって


newhairetu[0]

newhairetu[1]

newhairetu[2]

newhairetu[3]

newhairetu[4]


に格納されている値を変更できるというわけです。」


ソーラー


「main関数内で作製された配列newhairetuの


配列変数


newhairetu[0]

newhairetu[1]

newhairetu[2]

newhairetu[3]

newhairetu[4]


に格納されている値が


自作関数の操作をうけて変更される・・・


そうそう これは(^_^)v


まさに ポインタ渡しのときに起こるパターンだったね」


アレサ「今のプログラムでは


main関数内で


自作関数newmadefunction(int *hairetu)


の引数となっているポインタ変数hairetu



main関数内で定義された配列のアドレスを


格納しているポインタ変数newhairetu


が代入された命令文


newmadefunction(newhairetu);


が記述されています


このように


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


自作関数の引数のint *hairetuによって作製された


ポインタ変数hairetuに代入することにより


自作関数を使って


配列newhairetuに格納されている数値の値が


変更できるようになります。


これは先のポインタ渡しのエピソードにおいて


自作関数newmadefunction(int *ptx)の


()内でポインタ変数宣言された


ポインタ変数ptxに


main関数で定義された変数aのアドレス&aを代入する


ポインタ渡しの関係といっしょですの。


このときも


ポインタ変数ptxに


main関数内で定義された変数aのアドレス&aを代入する


ことにより


*ptxを自作関数の定義にもちいた


自作関数を使って


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


数値の値を変更できるようになりました。


つまり int *hairetuにより作製されるポインタ変数hairetu


はポインタ変数ptxにあたり


newhairetuは変数aのアドレス&aにあたるというわけですの。」


ソーラー「ポインタ変数宣言


int *hairetu



hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


だけでなく

hairetu

hairetu+1

hairetu+2

hairetu+3

hairetu+4


もつくっているか・・・


そんな仕組みだったんだね


アレサ ありがとう」




アレサ「お役に立てて嬉しいですの」




ソーラー「だから


配列newhairetu


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


を自作関数の引数int *hairetuに代入するということは


つまり


hairetu=newhairetu;

(hairetu+1)=(newhairetu+1);

(hairetu+2)=(newhairetu+2);

(hairetu+3)=(newhairetu+3);

(hairetu+4)=(newhairetu+4);


を実行していることになるんだね。


その際


newhairetu

newhairetu+1

newhairetu+2

newhairetu+3

newhairetu+4


を代表して


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



          newhairetuを



配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


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

hairetu

hairetu+1

hairetu+2

hairetu+3

hairetu+4


を代表している


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


hairetu


に代入しているんだね。」




アレサ「はい、そうですの


そして


このプログラムにおいて


配列newhairetuの


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


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


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


代入したように


一般に、



自作関数()内で(int *hairetu)のように


ポインタ変数宣言されたポインタ変数hairetuに


main関数内で定義された配列(例newhairetu)のアドレスを渡すには


main関数内で定義された配列(例newhairetu)のアドレスを


格納したポインタ変数


つまり


配列名(例newhairetu) を


自作関数()内で(int *hairetu)のように


ポインタ変数宣言されたポインタ変数hairetuに


代入するルールとなっています。


そうして


newmadefunction(newhairetu);


のように


自作関数の引数として


newmadefunction(int *hairetu)


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


hairetuに


main関数内で定義された配列newhairetuのアドレスを


格納しているポインタ変数newhairetuが代入されたなら


*hairetu

*(hairetu+1)

*(hairetu+2)

*(hairetu+3)

*(hairetu+4)



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


の配列変数

newhairetu[0]

newhairetu[1]

newhairetu[2]

newhairetu[3]

newhairetu[4]


のアクセスしているメモリにアクセスすることになり



main関数内で定義された配列newhairetuに格納されている数値は


*hairetu=*hairetu*2;

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

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

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

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


の自作関数の操作を受けて


変更できるようになります



このプログラムでは


main関数内での配列宣言


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


により生成された


配列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


と格納されていた数値が


自作関数の操作を受けて


newhairetu[0]=2

newhairetu[1]=4

newhairetu[2]=6

newhairetu[3]=8

newhairetu[4]=10


となっているのがわかります」


ソーラー「配列newhairetuに格納されている数値が2倍されているね。


ポインタ渡しを行うことにより


自作関数をつかって


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


格納されている数値を2倍に成功\(^o^)/💖したってわけだね」


アレサ


「ここで 


newhairetu[0]

newhairetu[1]

newhairetu[2]

newhairetu[3]

newhairetu[4]


のアドレス


&newhairetu[0]

&newhairetu[1]

&newhairetu[2]

&newhairetu[3]

&newhairetu[4]


を格納しているポインタ変数は


newhairetu

newhairetu+1

newhairetu+2

newhairetu+3

newhairetu+4


となっています


このように


ポインタ変数newhairetuは


配列newhairetu内の


5つの配列変数


newhairetu[0]

newhairetu[1]

newhairetu[2]

newhairetu[3]

newhairetu[4]


の先頭の


newhairetu[0]のアドレス


&newhairetu[0]を格納していながら


かつ


配列newhairetuを代表する


ポインタ変数となっていますね


ポインタ変数newhairetuを


int *hairetu[]により作製されるポインタ変数hairetuに渡せば


ポインタ変数

newhairetu

newhairetu+1

newhairetu+2

newhairetu+3

newhairetu+4



ポインタ変数

hairetu

hairetu+1

hairetu+2

hairetu+3

hairetu+4


hairetu=newhairetu;

(hairetu+1)=(newhairetu+1);

(hairetu+2)=(newhairetu+2);

(hairetu+3)=(newhairetu+3);

(hairetu+4)=(newhairetu+4);


このように


代入されるよう設定されているのですの」



ソーラー 「配列newhairetuのアドレスを格納している


ポインタ変数


newhairetu

newhairetu+1

newhairetu+2

newhairetu+3

newhairetu+4


をnewhairetuで1括して


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


自作関数newhairetu(int *hairetu)


と記述するシステムがC言語では用意されているんだね。


もうちょっと別の言い方をすると


自作関数newhairetu(int *hairetu)の引数であるポインタ変数hairetu


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


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


次のようなことがおこなわれています


ポインタ変数宣言


int *hairetuによって


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]



配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


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


hairetu

hairetu+1

hairetu+2

hairetu+3

hairetu+4



ともに生成されています


そして


ポインタ変数hairetuは


配列変数

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


hairetu[0]のアドレスは


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


を代表しているアドレスともいえるね。


hairetu[0]のアドレスは


配列hairetuのアドレスになっているともいえるかな


同様に


ポインタ変数newhairetuは


newhairetu[0]のアドレスを格納しているポインタ変数であり


newhairetu[0]のアドレスは


配列newhairetuのアドレスでもあるね。


だから

ポインタ変数宣言


int *hairetuに


よって生成されるポインタ変数


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のアドレスを格納しているポインタ変数


newhairetu



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


hairetu


に代入されているといえるかな」