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

てんC

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


#include <iostream>


using namespace std;



int main (){

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

int i;

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

cout<<hairetu[i]<<"\n";

return 0;

}


ビルド実行結果

1

2

3

4

5



てんC「

このプログラムでは配列hairetuの配列変数に

1,2,3,4,5の5つの数値データをとりこみ


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

cout<<hairetu[i]<<"\n";の命令文により


1

2

3

4

5

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



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


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;


と取り込んでいると


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


てんC「はい。この配列宣言int hairetu[];


を自作関数の()の部分に引数として記入し


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


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


配列宣言int hairetu[]


に参照渡し(ポインタ渡し)することができます。」



ソーラー「ええ????


はへ?


なんのことかわからない?・?・・・」


マックス「俺もだぁぁぁぁぁぁぁぁぁ」


青空にシャウトする。


てんC「それでは


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


次のプログラムをみていきましょう。」


#include <iostream>


using namespace std;



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() {

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

newmadefunction(newhairetu);


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

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

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


int j;

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

cout << newhairetu[j]<< "\n";


return 0;

}


ビルド実行結果


2

4

6

8

10


てんC「このプログラムでは


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


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


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


そしてmain関数内で


新しくつくられた配列newhairetu


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


を自作関数


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


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



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


やはり


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


引数 int hairetu[]に


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


ポインタ変数newhairetuを


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


ソーラー「


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


ポインタ変数newhairetuを


自作関数の引数である


int hairetu[]に


代入する???


どういうこと?

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


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


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


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


てんC「ここでなぜ


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



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




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


(この仕組みはC言語から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^)/


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


てんC「ですが


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「


ですから


C言語の作者さんが


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


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



ソーラー「そ、そうだね」


感嘆するソーラー。



もうなんか いま ラーメン作ってます。私

ぶっとんでます


                 solarplexussより


てんC

このようにして

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


まさに 参照渡し(ポインタ渡し)が行われたときのパターンだったね」


てんC「今のプログラムでは


main関数内で


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



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


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


を代入する命令文


newmadefunction(newhairetu);


が記述されています


このように


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


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


自作関数を使って


main関数内で定義された配列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


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


てんC「はい


そして

このプログラムにおいて


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


配列newhairetu[]の


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


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


一般に、


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


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


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


格納したポインタ変数


つまり


配列名(例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^)/💖したってわけだね」


てんC

「ここで 


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言語でもC++言語でも用意されているんだね。


別の言い方をすると


配列宣言

int hairetu[]によって


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

(int hairetu[]には配列newhairetu[5]のアドレスを格納しているポインタ変数が代入されます

そして

生成されるhairetuの配列変数の数は


配列newhairetu[5]の要素数5により決定されます)



配列変数

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で共有
  • はてなブックマークでブックマーク

作者を応援しよう!

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

応援したユーザー

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

新規登録で充実の読書を

マイページ
読書の状況から作品を自動で分類して簡単に管理できる
小説の未読話数がひと目でわかり前回の続きから読める
フォローしたユーザーの活動を追える
通知
小説の更新や作者の新作の情報を受け取れる
閲覧履歴
以前読んだ小説が一覧で見つけやすい
新規ユーザー登録無料

アカウントをお持ちの方はログイン

カクヨムで可能な読書体験をくわしく知る