🌞🌞🌞ポインタ変数を使って文字列データをメモリに格納していく場合 1番最後にデータを格納したメモリのアドレスがポインタ変数に格納されます🌞🌞🌞

配列と違いポインタ変数はポインタ変数名を変更しなくても文字列を💖どんどん💖メモリに格納することができます

ソーラー「それでは


char hairetu[ ]="neko";

char *hairetu="neko";の



違いを考察してみるよ。


まずは

char hairetu[ ]="neko";

のように


配列を使って

文字列データ"neko"をメモリに格納してみます。


#include <stdio.h>


int main(void){


char hairetu[]="neko";


printf("%s\n",hairetu);


return 0;

}


コンパイル結果


EAZY IDECの場合

neko


Visual Studioの場合

neko


アレサ「ソーラーさん


普通に配列を使って


メモリに


文字列データ"neko"が格納され


printf("%s\n",hairetu);


により


コマンドプロンプト画面に


neko


が表示されていますね。


このとき


配列hairetuの


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


には

n

e

k

o

\0

hairetu[0]='n'

hairetu[1]='e'

hairetu[2]='k'

hairetu[3]='o'

hairetu[4]='\0'


と格納されています。」


ソーラー「そうだね。


配列名はhairetuのまま


配列hairetuに


今度は


char hairetu[ ]="neko";

char hairetu[ ]="nyao";


のように


文字列データ"neko"

のあとに

文字列データ"nyao"


をメモリに格納するプログラムを実行してみるね。


#include <stdio.h>


int main(void){


char hairetu[ ]="neko";

char hairetu[ ]="nyao";


printf("%s\n",hairetu);


return 0;

}


コンパイル結果


EAZY IDEC の場合

nyao



Visual Studioの場合


エラー C2374 'hairetu': 再定義されています。2 回以上初期化されています。


アレサ「まずは

EAZY IDEC の場合ですが


このとき


配列hairetuの


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


には

'n'

'y'

'a'

'o'

'\0'

hairetu[0]='n'

hairetu[1]='y'

hairetu[2]='a'

hairetu[3]='o'

hairetu[4]='\0'


と格納されています。


最初に


配列hairetuの


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]



hairetu[0]='n'

hairetu[1]='e'

hairetu[2]='k'

hairetu[3]='o'

hairetu[4]='\0'


と格納されていた

文字データ

'n'

'e'

'k'

'o'

'\0'



配列変数

hairetu[5]

hairetu[6]

hairetu[7]

hairetu[8]

hairetu[9]

にずれる形で


hairetu[5]='n'

hairetu[6]='e'

hairetu[7]='k'

hairetu[8]='o'

hairetu[9]='\0'


と格納されています


つまり


メモリ内には


'n'

'e'

'k'

'o'

'\0'


'n'

'y'

'a'

'o'

'\0'


が格納されていますが


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


に格納されている文字データは


'n'

'y'

'a'

'o'

'\0'

になっているのですね」



ソーラー「次は


ポインタ変数hairetuを使って文字列データ"neko"をメモリに格納してみるね。


#include <stdio.h>


int main(void){


char *hairetu="neko";


printf("%s\n",hairetu);


return 0;

}


コンパイル結果


EAZY IDECの場合

neko


Visual Studioの場合

neko



アレサ「char *hairetu="neko";


hairetuのポインタ変数宣言,初期化を行って



文字列データ"neko"をメモリに格納しているのですが


このときも


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

が生成されて


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

には


文字データ

'n'

'e'

'k'

'o'

'\0'


hairetu[0]='n'

hairetu[1]='e'

hairetu[2]='k'

hairetu[3]='o'

hairetu[4]='\0'


と格納されています。(いるようにみえます)」


ソーラー「そうだね。


ここまでは配列をつかって


char hairetu[]="neko";


のように


文字列データ"neko"を


メモリに格納したときと同じだね。


今度は


ポインタ変数名はhairetuのまま


char *hairetu="neko";

char *hairetu="nyao";

のように


char *hairetu="neko";

のあとに

char *hairetu="nyao";

と記述して


文字列データ"neko"

につづいて

文字列データ"nyao"


メモリに格納するプログラムを実行してみるね。


#include <stdio.h>


int main(void){


char *hairetu="neko";

char *hairetu="nyao";


printf("%s\n",hairetu);


return 0;

}


コンパイル結果

EAZY IDECの場合

nyao


Visual Studioの場合


エラー C2374 'hairetu': 再定義されています。2 回以上初期化されています。


ソーラー「Visual Studioをお使いの方は


次のようにプログラムを記述してくださいね。」


#include <stdio.h>


int main(void){


char *hairetu="neko";

hairetu="nyao";


printf("%s\n",hairetu);


return 0;

}


コンパイル結果

nyao


ソーラー「このように


プログラムを記述しておけば


char *hairetu="neko";

hairetu="nyao";


のように


hairetuのポインタ変数宣言を1回行って


作製されたポインタ変数hairetuを


🍓文字列データ"neko"を格納しているメモリのアドレス🍓


で初期化した後


(char *hairetu="neko";


はポインタ変数hairetuを


文字列データ"neko"を格納しているメモリのアドレス


で初期化されます)


次に


hairetu="nyao";

により


ポインタ変数hairetuに


🍓文字列データ"nyao"を格納しているメモリのアドレス🍓


を代入することになりますが


hairetuのポインタ変数宣言が2度行われているわけではないので


ビルドエラーがおこることはありません。」




☆  ☆  ☆  ☆  ☆  ☆  ☆


この


Visual Studioの場合のプログラムを


EAZY IDECでもコンパイル、実行できるので


EAZY IDECでも


基本的にはこのように


記述したほうがよいとおもわれます。


同じ変数名の変数宣言や同じ配列名の配列宣言


同じポインタ変数名のポインタ変数宣言


を何回も行っていると意図しないコンパイル結果になる可能性が


あります。


このエピソードではわかりやすく説明するために


同じポインタ変数名のポインタ変数宣言


を何回も行っています。


                 solarplexussより




アレサ「


char *hairetu="neko";


のようにポインタ変数hairetuを使って


文字列データ"neko"をメモリに格納した後に


(このとき、ポインタ変数hairetuに代入されているのは


文字列データ"neko"を格納しているメモリのアドレスです)


char *hairetu="nyao";


のようにポインタ変数hairetuを使って


文字列データ"nyao"をメモリに格納しているのですが

(このとき、ポインタ変数hairetuに代入されているのは


文字列データ"nyao"を格納しているメモリのアドレスです)


このときも

配列hairetuの時と同じように


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

が生成され


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

には

文字データ

'n'

'y'

'a'

'o'

'\0'


hairetu[0]='n'

hairetu[1]='y'

hairetu[2]='a'

hairetu[3]='o'

hairetu[4]='\0'


と格納されています。(いるようにみえます)


         🍑このとき🍑


最初に


hairetuのポインタ変数宣言、初期化の命令文


char *hairetu="neko";


が実行されて


メモリに格納された

文字列データ"neko"の

文字データ

'n'

'e'

'k'

'o'

'\0'



文字列データ"nyao"

文字データ

'n'

'y'

'a'

'o'

'\0'

によって上書きされて消えてしまったわけではありません。


ここで


配列を使って文字列データを格納するときと

ポインタ変数を使って文字列データを格納するときの違いが


すこしだけ出てきます


配列hairetuを使って文字列データ"neko"をメモリに格納する場合


char hairetu[]="neko";

を実行した場合

配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

には

文字データ

'n'

'y'

'a'

'o'

'\0'

配列変数

hairetu[5]

hairetu[6]

hairetu[7]

hairetu[8]

hairetu[9]

には

文字データ

'n'

'e'

'k'

'o'

'\0'

格納されることになりましたが


ポインタ変数hairetuを使って文字列データ"neko"をメモリに格納する場合


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

には

文字データ

'n'

'y'

'a'

'o'

'\0'

格納されますが

配列変数

hairetu[5]

hairetu[6]

hairetu[7]

hairetu[8]

hairetu[9]

には

文字データ

'n'

'e'

'k'

'o'

'\0'

格納されません。


次のプログラムを実行してそのことを確認してみます。


#include <stdio.h>


int main(void) {


char *hairetu = "neko";

hairetu = "nyao";

printf("%c\n", hairetu[0]);

printf("%c\n", hairetu[1]);

printf("%c\n", hairetu[2]);

printf("%c\n", hairetu[3]);

printf("%c\n", hairetu[4]);

printf("%c\n", hairetu[5]);

printf("%c\n", hairetu[6]);

printf("%c\n", hairetu[7]);

printf("%c\n", hairetu[8]);

printf("%c\n", hairetu[9]);

return 0;

}


コンパイル結果


n

y

a

o


配列変数

hairetu[5]

hairetu[6]

hairetu[7]

hairetu[8]

hairetu[9]

には

文字列データ"neko"が格納されていませんので

空白が表示されています。


正確には

\0が格納されているので

空白が表示されています。


ですが

メモリ内には


文字列データ"neko"も

文字列データ”nyao”も


保存されたままとなっています。」


ソーラー「???????


配列変数

hairetu[5]

hairetu[6]

hairetu[7]

hairetu[8]

hairetu[9]

には

文字列データ"neko"が格納されていないのなら


文字列データ"neko"は


メモリから消えてしまっているのじゃないかな?


たとえば


hairetu[0]='n'

hairetu[1]='e'

hairetu[2]='k'

hairetu[3]='o'

hairetu[4]='\0'


格納された


文字列データ"neko"の

'n'

'e'

'k'

'o'

'\0'


文字列データ"nyao"が


配列変数

hairetu[0]='n'

hairetu[1]='y'

hairetu[2]='a'

hairetu[3]='o'

hairetu[4]='\0'


と格納されることにより


上書きされ

メモリからデータが

消えてしまっているんじゃないかな?????」


アレサ「ここがポインタ変数さんの可愛らしいところなんですの。


たとえば


次のようなプログラムが実行された場合→」


(EAZY IDECの場合)


#include <stdio.h>


int main(void){


char *hairetu="neko";

char *hairetu="nyao";

char *hairetu="myao";

char *hairetu="syao";

char *hairetu="cyao";

printf("%s\n",hairetu);


return 0;

}


コンパイル結果

cyao



(Visual Studioの場合


次のようにプログラムを記述してください)


#include <stdio.h>


int main(void){


char *hairetu="neko";

hairetu="nyao";

hairetu="myao";

hairetu="syao";

hairetu="cyao";

printf("%s\n",hairetu);


return 0;

}


コンパイル結果

cyao



アレサ「コンパイル結果


cyao


が表示されるのですが


このとき


文字列データ

"neko"

"nyao"

"myao"

"syao"

             すべて🍓🍓🍓


後の文字列データに上書きされることなく🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓


メモリ内に保存されていきます。🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓


つまり


       同じポインタ変数名hairetuを🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓


       つかっているにもかかわらず


文字列データ"neko"に続いて


どんどん


新たな文字列データ


"nyao"

"myao"

"syao"

"cyao"



別べつのメモリに


格納されていくのです。



このとき


1番最後にメモリに格納された🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓



文字列cyaoを格納しているメモリのアドレス🍓🍓🍓🍓🍓🍓🍓


ポインタ変数hairetu🍓🍓🍓🍓🍓🍓🍓


に格納されています。


そして


最後に


文字列データ"cyao"をメモリに格納する

char *hairetu="cyao";

が実行されると


char hairetu[ ]="cyao";の時と同じように


配列変数


hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

が生成されて

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

には

文字データ

'c'

'y'

'a'

'o'

'\0'


hairetu[0]='c'

hairetu[1]='y'

hairetu[2]='a'

hairetu[3]='o'

hairetu[4]='\0'


と格納されています。


そして

ポインタ変数hairetuには


文字列データ"cyao"


を格納しているメモリのアドレス


が格納されているので


printf("%s\n",hairetu);


によって表示される文字列は


cyaoになります。


つまり


1番最後のポインタ変数宣言、初期化の命令文


char *hairetu="cyao";


が実行されることにより


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

には

hairetu[0]='c'

hairetu[1]='y'

hairetu[2]='a'

hairetu[3]='o'

hairetu[4]='\0'

文字データが格納されています。


そして


ポインタ変数hairetuには


文字列データ"cyao"を格納しているメモリのアドレスが


格納されているので


printf("%s\n",hairetu);


を実行すると


cyao



コマンドプロンプト画面に表示されます。


ですので



それまでにメモリに格納された


文字列データ

"neko"

"nyao"

"myao"

"syao"

printf("%s\n",hairetu);


を実行しても


コマンドプロンプト画面に表示することはできなくなりますし




配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

をもちいて


printf("%c\n",hairetu[0]);

printf("%c\n",hairetu[1]);

printf("%c\n",hairetu[2]);

printf("%c\n",hairetu[3]);

printf("%c\n",hairetu[4]);


を実行しても

コンパイル結果は

c

y

a

o

空白

表示されます


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

以降の


配列変数

hairetu[5]

hairetu[6]

hairetu[7]

hairetu[8]

hairetu[9]

には何も文字列データが格納されていないので


(実際には\0が格納されています)


配列変数を使っても

文字列データ

"neko"

"nyao"

"myao"

"syao"

コマンドプロンプト画面に表示することはできないのですの」