天国にいけるC言語入門 ヘキサ構造体 ver2.2126
文字列データ"neko"をコンピュータのメモリに格納する char hairetu[]="neko"; と char* hairetu="neko"; では何がちがうのでしょうか?
文字列データ"neko"をコンピュータのメモリに格納する char hairetu[]="neko"; と char* hairetu="neko"; では何がちがうのでしょうか?
Visual Studio2019以降のヴァージョンではポインタ変数を使って文字列データをメモリに格納する機能は削除されました
ご注意ください
文字列データ"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
005BFD84
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というアドレス番号
のメモリ
に格納されている文字データ
'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]);
が実行されると
コンパイル結果は
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
*(hairetu+1)
*(hairetu+2)
*(hairetu+3)
*(hairetu+4
は
配列変数
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というアドレス番号
のメモリに
に格納されている文字データをあらわすことになったというわけです。
ですので
このとき
コンピュータのメモリ装置には
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というアドレス番号
のついたメモリに
アクセスすることができるというわけです。
次に
今のように
hairetu
の
char*型のポインタ変数宣言を行い作製されたポインタ変数を使って
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'
と格納されます。
そして
char* hairetu="nyao";
の実行により
先頭のアドレス番号00D3FA41のアドレスが
ポインタ変数hairetuに格納されることにより
アドレス番号
00D3FA41
00D3FA42
00D3FA43
00D3FA44
00D3FA45
が
与えられた結果
hairetu
hairetu+1
hairetu+2
hairetu+3
hairetu+4
に
アスタリスク*を用いた
*hairetu
*(hairetu+1)
*(hairetu+2)
*(hairetu+3)
*(hairetu+4)
は
アドレス番号00D3FA41
アドレス番号00D3FA42
アドレス番号00D3FA43
アドレス番号00D3FA
アドレス番号00D3FA45
のついたメモリに
格納されている文字データ
'n'
'y'
'a'
'o'
'\0'
をあらわすことになります。
*hairetu
*(hairetu+1)
*(hairetu+2)
*(hairetu+3)
*(hairetu+4)
は
hairetu[0]
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のメモリに'o'
アドレス番号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
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";
を実行したときとは違い
必ずしも連続して
文字データがメモリに格納されるとはかぎりません」
新規登録で充実の読書を
- マイページ
- 読書の状況から作品を自動で分類して簡単に管理できる
- 小説の未読話数がひと目でわかり前回の続きから読める
- フォローしたユーザーの活動を追える
- 通知
- 小説の更新や作者の新作の情報を受け取れる
- 閲覧履歴
- 以前読んだ小説が一覧で見つけやすい
アカウントをお持ちの方はログイン
ビューワー設定
文字サイズ
背景色
フォント
組み方向
機能をオンにすると、画面の下部をタップする度に自動的にスクロールして読み進められます。
応援すると応援コメントも書けます