文字列nekoをコンピュータのメモリに格納する char hairetu[]="neko"; と char *hairetu[]="neko"; では何がちがうのでしょうか?

文字列データ"neko"をコンピュータのメモリに格納する


配列宣言

char hairetu[]="neko";

ポインタ変数宣言

char *hairetu[]="neko";


では何がちがうのでしょうか?


ソーラー「よしっ それでは説明といこうかな。 アレサ。」


アレサ「はいっ ソーラーさん。」


ソーラー「まずは

char hairetu[]="neko";

からだね。


配列宣言

char hairetu[]="neko";


が行われると


文字列データ"neko"は


配列宣言


char hairetu[]="neko";


により生成される


char型の配列変数

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'


のように格納されます。


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


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

が作成されたようにみえます。



     🍓🍓 実はchar hairetu[]="neko";が実行されると🍓🍓



文字列データ"neko"を格納した


つまり


文字データ


'n'

'e'

'k'

'o'

'\0'


を格納した


というメモリが存在しており


例えていえば


005BFD83

05BFD84

005BFD85

005BFD86

005BFD87


というアドレス番号のメモリが存在しており


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

と名前のつけられたメモリが存在しているわけではありません。


配列変数


hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]



005BFD83

005BFD84

005BFD85

005BFD86

005BFD87


というアドレス番号のメモリに


アクセスするための窓口になっているのです。


そのことは

  


     🍋ポインタ変数宣言 char *hairetu="neko";🍋



が行われた場合でもおなじことなのです


char *hairetu="neko";

が実行されたときも


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

が作製されますが



hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


と名前の付けられたメモリに直接


文字列データ"neko"が

hairetu[0]='n'

hairetu[1]='e'

hairetu[2]='k'

hairetu[3]='o'

hairetu[4]='\0'


と格納されているわけではありません。


いったいど~いうこと???


とおもわれますね。



char hairetu[]="neko";

文字列"neko"データを格納したとき

ポインタ変数を使って

char *hairetu[]="neko";


文字列"neko"データを格納したときも


おなじようなことがおこなわれています。



ポインタ変数を使って


文字列データを格納する命令文


char *hairetu="neko";


が実行されると



まず コンピューターのあるどこかの

メモリ


例えるなら


0019FF54

0019FF55

0019FF56

0019FF57

0019FF58

というアドレス番号のメモリに


0019FF54というアドレス番号の付いたメモリに'n'

0019FF55というアドレス番号の付いたメモリに'e'

0019FF56というアドレス番号の付いたメモリに'k'

0019FF57というアドレス番号の付いたメモリに'o'

0019FF58というアドレス番号の付いたメモリに'\0'


のように




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


どのメモリに格納されるかはメモリの使用状況によります。


そして

その次は

char *hairetu="neko";

により

文字列データ"neko"が格納されたメモリのアドレス


つまり


文字データ'n'を格納したメモリのアドレス


0019FF54



ポインタ変数hairetuに格納されることになります。


文字列データ"neko"が格納されたメモリのアドレス


つまり


文字データ'n'を格納したメモリのアドレス


0019FF54



ポインタ変数hairetu


に格納されるとどういうことがおこるのでしょうか??


そのとき


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


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


hairetu

hairetu+1

hairetu+2

hairetu+3

hairetu+4


には

0019FF54というアドレス番号

0019FF55というアドレス番号

0019FF56というアドレス番号

0019FF57というアドレス番号

0019FF58というアドレス番号


があたえられることになります。


そのとき


*hairetu

*(hairetu+1)

*(hairetu+2)

*(hairetu+3)

*(hairetu+4)


0019FF54というアドレス番号

0019FF55というアドレス番号

0019FF56というアドレス番号

0019FF57というアドレス番号

0019FF58というアドレス番号

に格納されている文字データを表すことになるのですが



配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

は実は

*hairetu

*(hairetu+1)

*(hairetu+2)

*(hairetu+3)

*(hairetu+4)

をあらわしており


配列変数


hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

0019FF54というアドレス番号

0019FF55というアドレス番号

0019FF56というアドレス番号

0019FF57というアドレス番号

0019FF58というアドレス番号


のついたメモリ

に格納されている文字データをあらわすことになります。


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

0019FF54というアドレス番号

0019FF55というアドレス番号

0019FF56というアドレス番号

0019FF57というアドレス番号

0019FF58というアドレス番号


のメモリ

に格納されている文字データをあらわすので


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

が実行されると


配列変数


hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

に文字データ

'n'

'e'

'k'

'o'

'\0'

が格納されているので


コンパイル結果は

n

e

k

o

(空白)

と表示されます



つまり 

ポインタ変数宣言


char *hairetu="neko";


が実行された場合


生成された配列変数


hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


に文字列データnekoが格納されているのではありません。


そうではなく


0019FF54というアドレス番号

0019FF55というアドレス番号

0019FF56というアドレス番号

0019FF57というアドレス番号

0019FF58というアドレス番号


のメモリに


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


それらのメモリのアドレスが


ポインタ変数hairetuに


つまり

配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


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


hairetu

hairetu+1

hairetu+2

hairetu+3

hairetu+4

格納された結果


*hairetu

*(hairetu+1)

*(hairetu+2)

*(hairetu+3)

*(hairetu+4)


0019FF54というアドレス番号

0019FF55というアドレス番号

0019FF56というアドレス番号

0019FF57というアドレス番号

0019FF58というアドレス番号


のメモリに


に格納されている文字データをあらわすことになり




配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

*hairetu

*(hairetu+1)

*(hairetu+2)

*(hairetu+3)

*(hairetu+4)


をあらわすので

配列変数


hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]



0019FF54というアドレス番号

0019FF55というアドレス番号

0019FF56というアドレス番号

0019FF57というアドレス番号

0019FF58というアドレス番号


のメモリに


に格納されている文字データをあらわすことになったというわけです。


ですので

このとき

コンピュータのメモリ装置には


0019FF54というアドレス番号

0019FF55というアドレス番号

0019FF56というアドレス番号

0019FF57というアドレス番号

0019FF58というアドレス番号


のメモリに


文字データ

'n'

'e'

'k'

'o'

'\0'


を格納した

メモリだけが存在しています。


文字データ

'n'

'e'

'k'

'o'

'\0'

を格納した

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

と名付けられたメモリは存在していません。


ですが


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


を用いて

0019FF54というアドレス番号


0019FF55というアドレス番号


0019FF56というアドレス番号


0019FF57というアドレス番号


0019FF58というアドレス番号


のメモリに

アクセスすることができるというわけです。



次に


今のように

ポインタ変数を使って

char *hairetu="neko";


と文字列データ"neko"を格納した後


さらに

同じ名前の


ポインタ変数hairetuを使って


hairetu="nyao";(Visual Studioの場合)

char *hairetu="nyao";


と文字列データ"nyao"を格納した場合について

考察してみます。


さきほど


char *hairetu="neko";


により


0019FF54というアドレス番号

0019FF55というアドレス番号

0019FF56というアドレス番号

0019FF57というアドレス番号

0019FF58というアドレス番号


のメモリに


文字データ

'n'

'e'

'k'

'o'

'\0'


が格納されました。


次に


hairetu="nyao";


が実行されると


0019FF54というアドレス番号

0019FF55というアドレス番号

0019FF56というアドレス番号

0019FF57というアドレス番号

0019FF58というアドレス番号


のメモリとは違う


アドレス番号


00D3FA41

00D3FA42

00D3FA43

00D3FA44

00D3FA45


のメモリに


文字列データ"nyao"は


アドレス番号00D3FA41のメモリに'n'

アドレス番号00D3FA42のメモリに'y'

アドレス番号00D3FA43のメモリに'a'

アドレス番号00D3FA44のメモリに'0'

アドレス番号00D3FA45のメモリに'\0'


と格納されます。


アドレス番号


00D3FA41

00D3FA42

00D3FA43

00D3FA44

00D3FA45


は説明のための仮のアドレス番号です。



このとき


hairetu="nyao";


により生成された配列変数


hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


文字列データ"nyao"が

hairetu[0]='n'

hairetu[1]='y'

hairetu[2]='a'

hairetu[3]='o'

hairetu[4]='\0'


と格納されているのではありません。


繰り返して述べますと


hairetu="nyao";


により

まず

アドレス番号

00D3FA41

00D3FA42

00D3FA43

00D3FA44

00D3FA45


のメモリに


文字列データ"nyao"が


アドレス番号00D3FA41のメモリに'n'

アドレス番号00D3FA42のメモリに'y'

アドレス番号00D3FA43のメモリに'a'

アドレス番号00D3FA44のメモリに'0'

アドレス番号00D3FA45のメモリに'\0'


と格納されます。


そして


先頭のアドレス番号00D3FA41のアドレスが


char *hairetu="nyao";


により


ポインタ変数hairetuに格納されることにより


アドレス番号


00D3FA41

00D3FA42

00D3FA43

00D3FA44

00D3FA45



配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


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


hairetu

hairetu+1

hairetu+2

hairetu+3

hairetu+4

に与えられた結果


*hairetu

*(hairetu+1)

*(hairetu+2)

*(hairetu+3)

*(hairetu+4)


アドレス番号00D3FA41

アドレス番号00D3FA42

アドレス番号00D3FA43

アドレス番号00D3FA44

アドレス番号00D3FA45


のメモリに


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


'n'

'y'

'a'

'o'

'\0'


をあらわすことになります。



hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

*hairetu

*(hairetu+1)

*(hairetu+2)

*(hairetu+3)

*(hairetu+4)

を表しているので


配列変数


hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]



アドレス番号00D3FA41

アドレス番号00D3FA42

アドレス番号00D3FA43

アドレス番号00D3FA44

アドレス番号00D3FA45


のメモリに

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


'n'

'y'

'a'

'o'

'\0'


をあらわすことになります。



そして

char *hairetu="neko";

のあと

hairetu="nyao";


が実行された

この状態の場合


0019FF54というアドレス番号

0019FF55というアドレス番号

0019FF56というアドレス番号

0019FF57というアドレス番号

0019FF58というアドレス番号


のメモリに


文字データ

'n'

'e'

'k'

'o'

'\0'


は保存されたまま

別の


アドレス番号

00D3FA41

00D3FA42

00D3FA43

00D3FA44

00D3FA45

のメモリに

文字列データ"nyao"が


アドレス番号00D3FA41のメモリに'n'

アドレス番号00D3FA42のメモリに'y'

アドレス番号00D3FA43のメモリに'a'

アドレス番号00D3FA44のメモリに'0'

アドレス番号00D3FA45のメモリに'\0'



文字列データ"nyao"が格納されることになります。


文字列データ"neko"を格納している


アドレス番号0019FF54

アドレス番号0019FF55

アドレス番号0019FF56

アドレス番号0019FF57

アドレス番号0019FF58

のメモリに


文字列データ"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]);

が実行されると


コンパイル結果は

n

y

a

o

(空白)

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


このとき

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

アドレス番号00D3FA41

アドレス番号00D3FA42

アドレス番号00D3FA43

アドレス番号00D3FA44

アドレス番号00D3FA45

のメモリに格納されている文字データ

'n'

'y'

'a'

'o'

'\0'


をあらわしており


アドレス番号0019FF54

アドレス番号0019FF55

アドレス番号0019FF56

アドレス番号0019FF57

アドレス番号0019FF58


のメモリに格納されている


文字データ

'n'

'e'

'k'

'o'

'\0'


をあらわすことにはならないので

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


を実行しても


アドレス番号0019FF54

アドレス番号0019FF55

アドレス番号0019FF56

アドレス番号0019FF57

アドレス番号0019FF58

のメモリに格納されている


文字データ

'n'

'e'

'k'

'o'

'\0'



printf出力表示することはできません。



そこで どうしても


文字列データ"neko"を

配列変数

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


を使って表示したい場合は


char *hairetu="neko";

hairetu="nyao";

が実行された後

さらに

hairetu="neko";

を実行すればよいことになります。


そのときは

さきほどの

アドレス番号0019FF54

アドレス番号0019FF55

アドレス番号0019FF56

アドレス番号0019FF57

アドレス番号0019FF58


のメモリに格納されている


文字列データ"neko"の


文字データ


'n'

'e'

'k'

'o'

'\0'


とは別に

さらに新たに


アドレス番号


00EFF32C

00EFF32D

00EFF32E

00EFF32F

00EFF330


のメモリに


アドレス番号00EFF32Cのメモリに'n'

アドレス番号00EFF32Dのメモリに'e'

アドレス番号00EFF32Eのメモリに'k'

アドレス番号00EFF32Fのメモリに'o'

アドレス番号00EFF330のメモリに'\0'


と文字列データ"neko"が格納されます。


そして

hairetu="neko";


が実行されると


生成された

配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


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

hairetu

hairetu+1

hairetu+2

hairetu+3

hairetu+4


には

アドレス番号


00EFF32C

00EFF32D

00EFF32E

00EFF32F

00EFF330


があたえられることになります。


*hairetu

*(hairetu+1)

*(hairetu+2)

*(hairetu+3)

*(hairetu+4)



アドレス番号00EFF32Cのメモリに格納されている文字データ'n'

アドレス番号00EFF32Dのメモリに格納されている文字データ'e'

アドレス番号00EFF32Eのメモリに格納されている文字データ'k'

アドレス番号00EFF32Fのメモリに格納されている文字データ'o'

アドレス番号00EFF330のメモリに格納されている文字データ'\0'


をあらわすことになります。


そうなると


配列変数


hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

*hairetu

*(hairetu+1)

*(hairetu+2)

*(hairetu+3)

*(hairetu+4)

をあらわしているので


配列変数


hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


の格納している文字データは


アドレス番号00EFF32Cのメモリに格納されている文字データ'n'

アドレス番号00EFF32Dのメモリに格納されている文字データ'e'

アドレス番号00EFF32Eのメモリに格納されている文字データ'k'

アドレス番号00EFF32Fのメモリに格納されている文字データ'o'

アドレス番号00EFF330のメモリに格納されている文字データ'\0'


となります。


ですので


このとき


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

が実行されると


コンパイル結果


n

e

k

o

(空白)

が表示されることになります。


それでは配列を使った


char hairetu[]="neko";

をつかって

文字列データ"neko"を格納したとき


ポインタ変数を使った

char *hairetu="neko";

をつかって

文字列データ"neko"を格納したとき


ではなにがちがうのかというと


それは


char hairetu[]="neko";

をつかって

文字列データ"neko"を格納したときでは


次に

hairetuとは別の配列hairetuboxを使った

char hairetubox[]="nyao";

をつかって

文字列データ"nyao"を格納したとき


'n'・・・アドレス005BFD83

'e'・・・アドレス005BFD84

'k'・・・アドレス005BFD85

'o'・・・アドレス005BFD86

'\0'・・・アドレス005BFD87


'n'・・・アドレス005BFD88

'y'・・・アドレス005BFD89

'a'・・・アドレス005BFD8A

'o'・・・アドレス005BFD8B

'\0'・・・アドレス005BFD8C


と順序良く並んで文字データが格納されていくのですが


ポインタ変数を使った

char *hairetu="neko";

をつかって

文字列データ"neko"を格納したときでは


次に


hairetu="nyao";

をつかって

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


'n'・・・アドレス0019FF44

'e'・・・アドレス0019FF45

'k'・・・アドレス0019FF46

'o'・・・アドレス0019FF47

'\0'・・・アドレス0019FF48


'n'・・・アドレス0019FF53

'y'・・・アドレス0019FF54

'a'・・・アドレス0019FF55

'o'・・・アドレス0019FF56

'\0'・・・アドレス0019FF57


のようにランダムにメモリに文字データが格納されます。


☆  ☆  ☆  ☆  ☆  ☆  ☆


'\0'・・・アドレス0019FF48

'n'・・・アドレス0019FF53


アドレス番号が


5ほどはなれています。


(アドレス番号がきれいに並ぶ場合もあります)


☆  ☆  ☆  ☆  ☆  ☆  ☆


このようにポインタ変数をつかって


char *hairetu="neko";


hairetu="nyao";


を実行して


文字列データ"neko"を


格納したあと


新たに文字列データ"nyao"を格納していく場合は


配列を使って


char hairetu[]="neko";


char hairetubox[]="nyao";


を実行したときとは違い


必ずしも連続して


文字データがメモリに格納されることはありません」