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

アレサ

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


#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に1,2,3,4,5の5つの数値をとりこみ


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

printf("%d\n",hairetu[i]);の命令文により


1

2

3

4

5

をprintf出力表示しています。



ソーラー「配列宣言、初期化の


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関数内で定義された別の配列内の配列変数のアドレス情報を


この自作関数の引数となった


配列宣言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が自作関数の引数の

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[]に代入しています・・・・・・



ここで注目するべきところは


やはり


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


引数 int hairetu[]に


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


ポインタ変数newhairetuを


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


ソーラー「


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


ポインタ変数newhairetuを


自作関数の引数である


int hairetu[]に


代入する???


どういうこと?

さすがに無理ぃぃぃぃぃぃ~~~


もう意味不明すぎてツッコミできません


配列にポインタ変数を代入する?


それはできないんじゃないかな?」


アレサ「ここでなぜ


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



    配列宣言int hairetu[]が行われているのか




   🐣なぜ そのようにC言語の作者は設定したのか 🐣





を考察していきます


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


ポインタ変数newhairetuがint hairetu[]に代入されるとき


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


自作関数の引数であるint hairetu[]の要素数が5となり


hairetuの配列宣言


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

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

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

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

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


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


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



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


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


アレサ「ですが


int hairetu[]が行われ


配列hairetu内に


配列変数


hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

が生成されると


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


hairetu

hairetu+1

hairetu+2

hairetu+3

hairetu+4

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


つまり


自作関数の引数である()内のint 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


を代入していると思われます。」


ソーラー「なんだってぇ~」


アレサ「


ですから


C言語の作者さんが


       自作関数の()内はint hairetu[]でいいや


と設定したのも自然なことだったかもしれないですの」



ソーラー「アレサ、もうなんか🌞 冴えっ、冴え🌞」



アレサ、もうなんか 冴えっ、冴え

ぶっとんでます

かんがえつくかな ふつう こんなこと?


                 solarplexussより


アレサ

このようにして

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=newhairetu;

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

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

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

(hairetu+4)=(newhairetu+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[]にポインタ変数newhairetuを渡して


newhairetu[0]

newhairetu[1]

newhairetu[2]

newhairetu[3]

newhairetu[4]

のアドレスを参照渡しすることにより


自作関数をつかって


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


配列変数


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[]);



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


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


を代入する命令文


newmadefunction(newhairetu);


が記述されています


このように


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


自作関数の引数のint hairetu[]に代入することにより


自作関数を使って


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


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



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


自作関数newmadefunction(int *ptx)の


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


ポインタ変数ptxに


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


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


このときも


ポインタ変数ptxに


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


ことにより


*ptxを使って


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


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


つまり int 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

hairetu+1

hairetu+2

hairetu+3

hairetu+4

を代表している


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


に代入しているといえるかもしれないね。」


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


そして

このプログラムにおいて


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


配列newhairetu[]の


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


自作関数newmadefunctionの引数(int hairetu[])に代入したように


一般に、


自作関数()内で配列宣言された配列(例int hairetu[])に


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


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


格納したポインタ変数


つまり


配列名(例newhairetu) を


自作関数()内で配列宣言された配列(例int hairetu[])に


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



そうして


newmadefunction(newhairetu);



自作関数内の引数として(int hairetu[])に


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


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


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


自作関数の操作を受けて


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


このプログラムでは


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


により生成された


配列newhairetu内の配列変数に


newhairetu[0]=1

newhairetu[1]=2

newhairetu[2]=3

newhairetu[3]=4

newhairetu[4]=5


と格納されていた数値が


自作関数の操作


*hairetu = *hairetu * 2;

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

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

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

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


を受けて


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[]に渡せば


ポインタ変数

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括して


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


自作関数(int hairetu[])


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


別の言い方をすると


配列宣言

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のアドレスでもあるね。


同様に


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


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



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

作者を応援しよう!

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

応援したユーザー

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