char* 宣言での配列要素アクセスについて
char*型で宣言したポインタ変数に対して
配列の要素でアクセスすると落ちてしまいます。
理由がよくわかりません。
以下コードになります。
(コードA)
char* pA = "123456789";
pA[2] = 'A';
以下のコードの場合は問題ありません。
(コードB)
char pB[] = "123456789";
pB[2] = 'B';
両者の違いがいまいちよく分かりません。
コードAでpA[2]のアドレスを確認すると、
pAのアドレス[+2]を指しているので問題ないともうのですが、
間違っているのでしょうか?
pAに対して特別な操作はしていません。
ご教授お願いいたします。
No.1ベストアンサー
- 回答日時:
>char* pA = "123456789";
>pA[2] = 'A';
メモリ上のどこかに"123456789"が格納され、その先頭アドレスがpAに格納されます。
メモリ上のどこかに格納されている"123456789"は「文字列定数」となります。
「定数」なので、通常は書き換えは許可されません。
>char pB[] = "123456789";
>pB[2] = 'B';
メモリ上(ローカル変数ならたいていはスタック領域上)に10バイトの領域を確保し、
その領域の初期値として"123456789"を格納しています。
こちらは通常内容が変化するものとして使用されるので、書き換えは可能です。
http://www9.plala.or.jp/sgwr-t/c/sec10-3.html
の【文字列リテラル】を参照されるとよいでしょう。
char* pA = "123456789";
char* pB = "123456789";
と記述した場合、指している文字列は同じですからコンパイラの最適化によってはpAとpBが同じアドレスを指す場合があります。
さて、文字列リテラルの書き換えを許可していたとて、*(pA+1) = 'B'が可能だった場合にpBが指す文字列はどうなるでしょう?
No.4
- 回答日時:
コードAの場合、文字列を格納するだけの領域を確保したうえで文字列をその領域にコピーするようにしなくてはなりません。
char* pA = (char*) malloc(10); /* 文字列のサイズ+1 のバッファを確保 */
strcpy(pA, "123456789");
pA[2] = 'A';
コードAのように
char* pA = "123456789";
としてしまうと、読み取り専用メモリに文字列"123456789"が格納されてしまい、その領域を書き換えようとすると落ちてしまいます。
No.3
- 回答日時:
コードA のように書いた場合, pA がさす文字列リテラルを変更してはいけないことになっています. イメージとしては, コードA では「文字列リテラル "123456789" はプログラムが直接管理しないどこかにあって pA はその領域を指す」, コードB は「プログラムで必要な領域を pB として確保しそこに文字列リテラル "123456789" と同じものを入れておく」という感じでしょうか.
本来文字列リテラルは「定数」であり, その型は const char [] であるべきものです. C では const のつかない char [] ですが, これは「そもそも const というものが存在しなかったはるか遠い過去」との互換性によるものであり, 「変更できないものである」と考えるべきです. ちなみに C++ では const char [] だけど特例で char * な変数にも代入できる (がそのような操作はすべきではない).
No.2
- 回答日時:
コードAは、(一般的に)書き換え不能領域に配置される文字列"123456789"の先頭アドレスをpAに与えます。
で、書き換え不能領域を書き変えようとするのでメモリ保護例外が出ます。
#環境によってたまーに例外があるので注意
コードBは、配列pBを"123456789"の値で初期化します。
こちらは書き換え可能領域内にあるので、自由に書き換えられます。
従って、配列のようにアクセスしたのが原因ではなくコードAでは*(pA+2)='A';でも同様にコケます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C言語初心者 構造体 課題について 2 2023/03/10 19:48
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# c言語 コマンドライン引数 4 2023/02/09 18:47
- JavaScript jQueryでのレスポンシブが綺麗に動かない 3 2022/06/21 11:08
- C言語・C++・C# C言語初心者 ポインタについて、お助けください、、 2 2023/03/15 23:50
- JavaScript jQueryで同じクラス名のものを別物として扱いたい 1 2022/06/17 14:14
- C言語・C++・C# C言語のファイル入力が分かりません 2 2022/05/22 06:35
- C言語・C++・C# C言語について コマンドラインで >変数 12.00 (char型) と、小数点付きの値を共用体に渡 1 2022/04/22 16:56
- C言語・C++・C# const char** p;のとき、free(p)でC4090エラーとなるのはなぜですか 3 2023/03/31 16:28
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語のintとcharの違いってな...
-
C言語のプログラムについてです
-
char*を初期化したいのですが
-
new charとnew char[N]の違いは?
-
CStringからchar*への型変換に...
-
入力された文字列の中の数字を...
-
小数点入りの文字列をfloat型に...
-
C言語にて構造体のメンバがNULL...
-
DWORDとcharの変換
-
fstream型オブジェクトを関数の...
-
文字列str内の全ての数字を...
-
文字列の途中から途中までを抽出
-
プログラムの中身の意味
-
wsprintf( ポインタ , "%d" , "...
-
szとlpszの違い
-
しつこい様ですが、再度ポイン...
-
警告 : 問題のあるポインタの変換
-
Vectorでヒープエラーが出る
-
char型にint型の数値を代入する。
-
char 文字列型 の表現範囲が-12...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
char*を初期化したいのですが
-
CStringからchar*への型変換に...
-
C言語にて構造体のメンバがNULL...
-
C言語のintとcharの違いってな...
-
小数点入りの文字列をfloat型に...
-
new charとnew char[N]の違いは?
-
const char* s1とただのchar s1...
-
DWORDとcharの変換
-
strcat関数を自作したいです
-
C++17で、unsigned char * 配列...
-
文字列内の数字削除
-
エクセルのMID関数は、C言語では?
-
char 文字列型 の表現範囲が-12...
-
char型にint型の数値を代入する。
-
C言語を用いた環境変数の作成/...
-
動的メモリの初期化方法について。
-
fstream型オブジェクトを関数の...
-
C言語のプログラムについてです
-
文字列の途中から途中までを抽出
-
C言語:小文字を大文字に変換す...
おすすめ情報