お世話になっております。
まると申します。
初歩的なことで申し訳ありませんが、ポインタとメモリについて教えてください。
(Windows環境です。)
例えば、文字列abcをポインタを使って参照したい場合、
char *P; ----①
p = abc ----②
と宣言した時、確保されるメモリは何バイトなのでしょうか?
今まで、①のようにポインタ宣言した場合、アドレスを格納する為のバイト数のみが
確保されて、実際に参照する先は配列や動的確保で確保するものと思ってました。
そして、参照先には、ただabcが入るだけで確保されないと思ってました。
しかし、ある参考書では上記のように使われていたので混乱してしまいました。
上記のように記述した場合でも、abcが入っている領域は保護されるのでしょうか?
基本的なことかもしれませんが、何卒ご教授ください。
よろしくお願い致します。
すみません。
間違えました。
>そして、参照先には、ただabcが入るだけで確保されないと思ってました。
正: 上記のような記述にすると、参照先には、ただabcが入るだけで確保されないと思って
ました。
よろしくお願い致します。
>char *P; ----①
>p = abc ----②
>と宣言した時、確保されるメモリは何バイトなのでしょうか?
4+4で8バイトかなぁ。
あってる、リサリサ?
まず、基本に戻って、
「ポインタは、アドレスを入れるための変数である」
^^^^
ということを考えてみてください。
ポインタといえどもただの変数です。
char *p; ....1
p = abc;...2
1の時点では、変数を宣言しているだけです。
普通の変数同様、pの中身は不定です。
通常ポインタは4バイト(32ビットマシン)です。
2はその変数に値をセットしているに過ぎません。
ただ、ポインタはアドレスを入れるという特性上、
abcという文字列の先頭のアドレスをいれています。
だから、abcの領域が確保されているかどうかというのは
発想が若干違っていて、abcという文字列の先頭の
アドレスをpにセットしているのです。
strcpyという関数のプロトタイプは
char *strcpy( char *string1, const char *string2 );
ですが、普通に
char buff[10];
strcpy(buff,abc);
ってつかいますよね?!このときabcの領域が確保されているか
とかって考えませんよね?!それと同じ事でとおもいますよ!
って、あんまり答えになってないですね・・・。ごめんなさい。
#丸付き数字はJIS X0208外の文字なので使わない方がよいです。
> char *P; ----(1)
> p = abc ----(2)
> と宣言した時、確保されるメモリは何バイトなのでしょうか?
Pがauto変数として,スタックにsizeof(char *),現行VC++では4バイト。
あと,abcの領域として,静的領域に4バイト確保されます。
Cだと,
static char temporary_[4] = { 'a', 'b', 'c', 0 };
char * p;
p = temporary_;
とやっているのと同じです。C++では,
static const char temporary_[4] = { 'a', 'b', 'c', 0 };
char * p;
p = const_char<char *>(temporary_);
と同じです。
> 上記のように記述した場合でも、abcが入っている領域は保護されるのでしょうか?
保護,というのが何を意味しているのかわかりませんが,CにしろC++にしろ,
書き換えたら動作は不定だったか未定義だったか……。
文字列リテラルが、あるプログラム中の複数箇所に出てきたとして、これが、それぞれ独立した
メモリに配置されるか、1つにまとめられるかは実装依存なので、注意する必要があります。
1つにまとめられた場合は、例えば、次のような現象が発生します。
ある個所でabcをbbcに書き換える処理を実行したとします。
また、まったく関係ない個所に、puts(abc);という記述があり、これを実行したとします。
すると、このputs(abc);の実行結果は、おそらくbbcが表示されることになります。
#それ以前に、YuOさんが指摘されているように、書替えの結果は未定義なのだが。
因みに、なぜ言語仕様上文字列リテラルがconstでないかですが、古いCとの互換性のためと
思われます。
ジョジョ@冒険さん、フマキラーさん、YuOさん、
早速お返事いただきありがとうございます。
また、丸付き文字の件、存じませんでした。申し訳ありません。
> 普通の変数同様、pの中身は不定です。
> abcという文字列の先頭のアドレスをいれています。
これは、YuOさんのおっしゃる通り、abc\0を静的領域に確保し、
そのアドレスをPに代入してると言う事ですね?
>保護,というのが何を意味しているのかわかりませんが,CにしろC++にしろ,
>書き換えたら動作は不定だったか未定義だったか……。
保護と言うのは、書き換えられるかどうか?と言う事だったのです。
静的に確保されると言う事は、書き換えられないと言う事ですよね?
ちなみに、質問しましたものと、
char *p;
strcpy(p,abc);
とは違いますよね?
もっとポインタを勉強しなければいけないですね。。。。
基本的なことばかりお聞きしてすみません。
クラフトマンさん、お返事ありがとうございます。
ただの文字列だと思っていましたが、いろいろ注意が必要なのですね。
勉強になります。
YuOさんもおっしゃってましたが、書換え後は未定義ですか。
気をつけたいと思います。
ひとことだけ。
char *p;
strcpy(p,abc);
は絶対やっちゃ駄目です。
なぜなら、変数宣言しただけのポインタは不定値で
メモリ上のあらぬところを指しているからです。
strcpyする前に必要なメモリ確保をきちんとしていれば、
問題はありません。
PATIOさん、お返事ありがとうございます。
>char *p;
>strcpy(p,abc);
>
>は絶対やっちゃ駄目です。
そうですよね。
ポインタが指し示す先にメモリを確保しなければだめですよね。
でも、
p = abc;
は、まずabcを静的に確保して、pにその先頭アドレスを入れるからOK!
ということで理解しました。
みなさまありがとうございました。
今後ともよろしくお願い致します。