こんにちは。
C言語を勉強しているのですが、どうしても分からないことがあるので質問しました。
まず下記のソースを見てください。
#include <stdio.h>
int main()
{
char* moji;
moji = "right Test \n";
printf(" moji = %s\n", moji);
moji = "dot 255 left up down \n";
printf(" moji = %s\n", moji);
getchar();
return 0;
}
char* mojiがメモリを取らずに代入できているのですがこういった事が可能なのは何故でしょうか?
その後もmojiの変数を別の文字列定数で書き換えています。
こういったことはできなかったはずなんですがどうしてでしょうか?
自分の開発環境だとVS.2005 VC++です。
よろしくおねがいします。
No.2ベストアンサー
- 回答日時:
>char* moji;
mojiはchar*型の変数です。
>moji = "right Test \n";
メモリ上のどこかに配置されている「文字列定数」のアドレスを代入しています。
# コンパイラとリンカがよろしく確保しています。
>moji = "dot 255 left up down \n";
同じく、メモリ上の別の場所に配置されている「文字列定数」のアドレスを代入しています。
別に不思議なことではありません。
アドレスを格納するだけの変数の領域は
>char* moji;
で確保されているのですから。
ただし…moji経由で内容を書き換えようとすると、不正終了する可能性があります。
moji = "right Test \n";
*(moji+1) = 'I';
とか、
moji = "right Test \n";
strcat(moji, "dot 255 left up down \n");
とか。
不正終了しない場合は……
moji = "right Test \n";
*(moji+1) = 'I';
moji = "right Test \n";
で、2回目の代入した際に書き換わっている可能性があります。
なるほど
# コンパイラとリンカが文字列定数のアドレスを用意しているため
それを代入しているんですね。
昔のコンパイラならエラーだったはずなのですが。
No.4
- 回答日時:
ポインタに対する代入演算子はmemcpyやstrcpyのようにポインタが示す先を書き換えるのではなく、ポインタそのものを置き換えるだけです。
回答ありがとうございます。
moji = "right Test \n";
上の文は文字列定数のアドレスをmojiに代入している
ということですね。
No.5
- 回答日時:
C言語の変数には{名前、アドレス、属性、値}というものが付随しています。
例えば、 int abc = 123 ; という変数では abc という名前と int という属性と 123 という値を持ちます。
アドレスは、静的変数の場合はコンパイラが決定しますが、動的変数では実行時に決定されます。
名前、アドレス、属性は変更できませんが、値は変更できます。
(属性については一時的な変更は可能)
名前はコンパイラだけが使用し、プログラムから操作する事は出来ません。
char* moji; の場合、moji という名前で、char へのポインタという属性を持ちます。
この場合の moji は動的変数なので関数が呼び出された時にアドレスが決まります。
その値は関数が呼び出された時点では不定です。
char へのポインタという属性は、その変数の値が char という属性を持つ別の変数のアドレスを示すという事を意味します。
(この、ポインタ変数というのが分かりにくい原因ですね)
moji = "right Test \n"; の場合、"right Test \n"という文字列をコンパイラが用意します。
この文字列の名前とアドレスはコンパイラが自動的に決めます。
値は"right Test \n"という文字列で、属性は const char です。
moji = "right Test \n"; を実行すると moji の値を"right Test \n"という文字(列)のアドレスに置き換えます。
moji の値は正しく"right Test \n"という文字列を示しているので printf() で出力する事が出来ます。
moji = "dot 255 left up down \n";では、
moji の値が"dot 255 left up down \n"; のアドレスに置き換えられるます。
moji の値は正しく"dot 255 left up down \n"を示しているので printf() で出力する事が出来ます。
"right Test \n" という文字列は const char という属性を持ちます。
const という属性は書き換え不能、または書き換え禁止という意味を持ちます。
無理に書き換えた時の動作は環境に依存します。
No.6
- 回答日時:
「ポインタそのもの」と「ポインタが指している内容」とは明確に区別してください. その上で, 「こういったこと」が「どういったこと」であるのか説明できますか?
以下余談:
たしかに「文字列リテラルを char* で扱う」のはあまりいいことではないけど, これがきちんと動くことは環境によらない>#3 し, まして「明らかな間違い」と言い切っちゃうのはいかがなものかと>#1.
ついでに C では「(配列の初期化で用いられていない) 文字列リテラル」の個々の文字は (const char ではなく) 「ただの char」 (ただし変更不可) だったりします>#5. C++ だと const char (でも文字列リテラル全体は char* 変換可能) と, これはこれでややっこしかったりしますが.
char* を使って文字列リテラルを扱うことが環境によらないこと
なんですね。たとえばVC++6.0でもこうなると。
自分の感想なんですが、char* だけで文字列リテラルを扱う場
合、前の質問者さんが指摘した部分で変数に代入する場合は
注意が必要だということですね。
それに気を付けていれば扱いやすいかもしれないと思いました。
今までは、 malloc, newして代入してたんで、このやり方を知ら
なかったです。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
CStringからchar*への型変換に...
-
char*を初期化したいのですが
-
関数内で設定したポインタ値に...
-
fstream型オブジェクトを関数の...
-
警告
-
strcat関数を自作したいです
-
SetWindowTextについて。
-
C++Builder 2009 テキスト...
-
C言語にて構造体のメンバがNULL...
-
文字列の途中から途中までを抽出
-
別ファイルの内容を検索したい...
-
C言語のintとcharの違いってな...
-
エクセルのMID関数は、C言語では?
-
#include <stdio.h> int main(v...
-
ポインタで詰まりました;
-
char型について【初心者です】
-
C言語入門者です。今ポインタの...
-
char型にint型の数値を代入する。
-
new charとnew char[N]の違いは?
-
char 文字列型 の表現範囲が-12...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
char*を初期化したいのですが
-
C言語のintとcharの違いってな...
-
CStringからchar*への型変換に...
-
C言語にて構造体のメンバがNULL...
-
fstream型オブジェクトを関数の...
-
小数点入りの文字列をfloat型に...
-
char型にint型の数値を代入する。
-
const char* s1とただのchar s1...
-
new charとnew char[N]の違いは?
-
動的メモリの初期化方法について。
-
エクセルのMID関数は、C言語では?
-
C言語 strstrの実装
-
SetWindowTextについて。
-
char 文字列型 の表現範囲が-12...
-
文字列の途中から途中までを抽出
-
2次元配列の文字"列"の初期化方法
-
DWORDとcharの変換
-
C++17で、unsigned char * 配列...
-
C言語の文字リテラル中の16進文...
-
strcat関数を自作したいです
おすすめ情報