- ベストアンサー
初心者です
char c[] = "XXX";と書くと配列cは書き換え可能なのに対して、 char* p = "XXX";と書くと*pの指す先が書き換え不可なのは 何故なのでしょうか? そういうものだから、以外でお願いします。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
「実体がどこにあるか?」が違うからです。 char c[3]; や char c[]="XXX"; と書くと「配列c」は「書き替え可能なメモリの上に実体が作られる」のです。 実は char c[]="XXX"; と書くと、コンパイラは char c[3]; memcpy(&c[0],"XXX",3); と同じ事をします。 つまり「書き替え不可な領域にある『"XXX"』を、書き替え可能な領域にあるcにコピーする」ので、cは"XXX"で初期化され、後からcの中身を書き替え出来るのです。 さて、 char *p="XXX"; と書くとコンパイラは char *p; p="XXX"; と同じ事をします。 「ポインタp」は「書き替え可能なメモリの上に実体が作られる」のは同じですが、そのメモリには「ポインタ」だけが存在します。 「書き替え可能なメモリ」には「pが指す先」ではなく「pそのもの」があるので、 p=NULL; とか p="XXX"; とか p=buf; とか、pそのものを自由に書き替える事が出来ます。 しかし、そのポインタが指す先の"XXX"は「固定データが置かれる、書き替え不可能なメモリ上にある」ので、pが指す先を書き替えようとすると例外が発生します。 「メモリの性質」を主観に、もう1度説明すると、以下のようになります。 メモリ領域は「コード領域」「固定データ領域」「可変データ領域」の3つに分類されます(本当はもっと複雑だけど、説明の為に省略) 「コード領域」は「プログラムの命令コード」つまりは「機械語」が収められた領域で、書き換えは不可になっています。 「固定データ領域」は「"で括った固定の文字列」や「初期化用データ」が納められた領域で、コード領域と同じく、書き換えは不可になっています。 「可変データ領域」は「変数の実体」が置かれ、自由に書き替え出来ます。 ●「char c[]="XXX";」の場合のメモリ配置 ・コード領域 memcpyを実行する命令コードが置かれる ・固定データ領域 "XXX"が置かれる ・可変データ領域 3バイトのメモリに「cの実体」が置かれる ●「char *p="XXX";」の場合のメモリ配置 ・コード領域 ポインタpに「"XXX"が置かれたアドレス」を格納する命令コードが置かれる ・固定データ領域 "XXX"が置かれる。pが指す先はここ。 ・可変データ領域 「アドレスを格納可能なサイズ」のメモリに「pの実体」が置かれる この状態では「&c[0]」は「可変データ領域」のアドレスを指します。なので「c[0]='A'」など、cの中身を書き替える事が出来ます。 そして「&p[0]」は「固定データ領域」のアドレスを指します。当然、書き替えようとすると例外が発生します。 char *p="XXX"; *p='A'; は (*((char *)"XXX"))="A"; と書くのと同じなので「"で括った固定の文字列は書き替え出来ねえ」と、例外が発生するのです。
その他の回答 (1)
- aris-wiz
- ベストアンサー率38% (96/252)
少し細かいですが。 >char c[]="XXX"; と書くと'\0'を伴って初期化されます。 上記のコードでのサイズは正確には char c[4]となります。 >memcpy(&c[0],"XXX",3); これでは\0が入りません。 #等価なのは strcpy( c, "XXX" )かな
お礼
とてもよくわかりました。 ありがとうございますーーー