ポインタを使った文字列の初期化でつまづいています.
char str[] = "hoge";
char* str2 = "piyo";
のように初期化した後では
printf("%c\n",str[0]); ->hが出力
printf("%c\n",str2[0]); ->pが出力
となるのですが,
str[0] = 'A'; <-OK
str2[0] = 'A'; <-エラー
とするとプログラムが落ちてしまいます.
ポインタの知識が乏しいのか,このエラーの原因がわかりません.
なにか参考になるページがありましたら教えていただけないでしょうか?
よろしくお願いいたします.
たぶん、実行時エラーとしてセグメンテーションエラーが出たのだと思います。
char str[] = "hoge"; char* str2 = "piyo";
上の行は"hoge"という文字列を「データ格納領域(データセグメント)」にある配列strにコピーします。
下の行は"piyo"という文字列が書かれた「プログラム格納領域(コードセグメント)」のアドレスをstr2に代入します。
一般にプログラム格納領域は変化してはいけない(読み出しのみ)になっているために書き込みをしようとするとOS(CPU)がエラーを出すのです。
これが組み込み用の8bitマイコンなんかだとそういうセグメントの概念がないのでたぶんエラーは出ないです。
もしポインターでやるのなら
char* p = malloc(5);
strcpy( p, "piyo");
みたいにポインタが、メモリ割り当て関数malloc()で割り当てられたデータ格納領域を指すようにするなどの必要があります。
http://itpro.nikkeibp.co.jp/article/COLUMN/20061023/251565/?ST=d...
http://itpro.nikkeibp.co.jp/article/COLUMN/20061128/255135/?ST=d...
char str[] = "hoge";
char* str2 = "piyo";
str2に文字というか数値を格納する場合
メモリを割り当てたり strのポインタにすればよいでしょう
str2 を maloc してみてはいかがでしょうか?
ありがとうございます.
malocを使うと正常に動作しました.
前者は動的領域にデータが確保されるので、
char str[] = "hoge";
は
char str[5] = { 'h', 'o', 'g', 'e', '\0' };
と等価ですが、後者はコンパイラによって定義されたデータ領域を指すポインタなので、その領域を変更することは動作的に正しくません。
コンパイラによって動くこともあるかもしれませんが、それは偶然(コンパイラの仕様)であって、データが静的領域を指す場合、今回のように access violation で落ちても、それは正常な動作です。
データ領域という概念を知りませんでした.
ありがとうございました.
たぶん、実行時エラーとしてセグメンテーションエラーが出たのだと思います。
char str[] = "hoge"; char* str2 = "piyo";
上の行は"hoge"という文字列を「データ格納領域(データセグメント)」にある配列strにコピーします。
下の行は"piyo"という文字列が書かれた「プログラム格納領域(コードセグメント)」のアドレスをstr2に代入します。
一般にプログラム格納領域は変化してはいけない(読み出しのみ)になっているために書き込みをしようとするとOS(CPU)がエラーを出すのです。
これが組み込み用の8bitマイコンなんかだとそういうセグメントの概念がないのでたぶんエラーは出ないです。
もしポインターでやるのなら
char* p = malloc(5);
strcpy( p, "piyo");
みたいにポインタが、メモリ割り当て関数malloc()で割り当てられたデータ格納領域を指すようにするなどの必要があります。
http://itpro.nikkeibp.co.jp/article/COLUMN/20061023/251565/?ST=d...
http://itpro.nikkeibp.co.jp/article/COLUMN/20061128/255135/?ST=d...
char str[] = "hoge";
char* str2 = "piyo";
では同じことをしているのかと思っていたのですが,全然意味が違うのですね・・・
おそらくC言語だと思われますが、下記のC-FAQ 1.32を参照してください
http://www.kouno.jp/home/c_faq/c1.html#32
> char str[] = "hoge";
> str[0] = 'A'; <-OK
これは5つの要素を持つ配列を定義してその0番目を書き換えただけなので問題ありません
# str[5] = 'A';とかすると未定義動作になります
# 未定義動作とは「何が起こってもよい」ということです
# 別のコンパイラだとプログラムが落ちない可能性もありますし、
# コンパイルオプションの変更や、何か処理を追加するだけで
# 動いたり、動かなくなったりします。
> char* str2 = "piyo";
> str2[0] = 'A'; <-エラー
これは文字列リテラルを指すポインタを定義して、
文字列リテラルを書き換えてしまったので未定義動作となります。
ポインタを使うときはその指し示す先に何があるのかを意識する必要があります。
ありがとうございました.
後者の書き方だと,ポインタの先が文字列リテラルのアドレスになるということがわかりました.
char str[] = "hoge";
char* str2 = "piyo";
では同じことをしているのかと思っていたのですが,全然意味が違うのですね・・・