10

重複の可能性:
C文字列定数を変更しますか?
const char vs char array vs std::stringへのポインタ

私はおそらくこの質問で死んだ馬を打ち負かしていることを知っていますが、私は少し混乱していて、SOまたはgoogleで正確な答えを見つけることができませんでした(私は正しいと確信しています-情報が多すぎますふるいにかけるCストリング上)。また、特にCスタイルの文字列について話しているにもかかわらず、私が興味を持っているのはC++というタグを付けました。

この状況では:

char const a*  = "hello";
char const b[] = "goodbye";

「hello」と「goodbye」はどちらも不変の文字列だと思っていたでしょう。なぜなら、それらは文字列リテラルから来ており、charconst*に減衰するはずだからです。

ただし、この特定のケースでは、b配列から定数を取り除いた場合、「こんにちは」の変更は定義されていませんが、「さようなら」の変更は問題ありません。

bの場合、文字列はユーザ​​ー定義の配列に格納されているため、文字列は変更可能であると思います。

この場合、こんにちはとさようならは違いますか? この例では、何らかの理由で文字列リテラルではなく、さようならです。また、さようならが文字列リテラルでない場合、それはグローバルメモリに保持されておらず、コンパイル後の参照はユーザー配列セルに残っているものだけであると想定できますか?

4

5 に答える 5

18

1つ目は、文字列リテラルを指すポインタを作成します"hello"。これは、プログラムの実行可能イメージの書き込み不可能なメモリに格納されている可能性があります。そうでない場合でも、その配列の内容を変更することは許可されていません。

2つ目は、自動配列1(通常はスタック上に(通常は実装定義です))を作成し、文字列で初期化します"goodbye"。と同等です

char const b[] = {'g', 'o', 'o', 'd', 'b', 'y', 'e', 0};

したがって、は書き込み不可能なメモリに格納され"goodbye"ている文字列リテラルであるため不変ですが、配列はマークを付けたため不変である自動1配列ですが、変数宣言からを削除して配列の内容を可変にすることができます。配列の内容を配列の内容で初期化するだけです。char const[8]bconstconst"goodbye"

どちらも変更可能であるため、どちらも変更することはできませんconst char[]が、2番目の変更は変更可能に変更できますがchar[]、最初の変更は変更できません。

詳細については、この回答を参照してください:https ://stackoverflow.com/a/9106798/726361


1 R. Martinho Fernandesがコメントで指摘したように、構文T x[] = ...が名前空間スコープにある場合、構文は静的配列(自動ではなく静的(通常は実行可能イメージ内ですが、実装が定義されています))を作成することもできます。それ以外の場合は配列。

于 2012-02-24T19:28:34.847 に答える
6

文字列リテラルの型はchar const[N];です。もちろん、このタイプの名前はに減衰する可能性がありchar const*ます。

今:

  1. 配列は文字char列リテラル(8.5.2 / 1)で初期化できますが、それ以外の方法では配列をコピーまたは割り当てることができないため、この初期化ではコピーが実装されます。新しい可変配列は、好きなように自由に使用できます。

    char str[6] = "hello";
    
  2. 逆に、ポインタを初期化すると、文字列リテラルの不変の配列型が減衰した結果であるポインタを取得することになります。

    char const* str = "hello";
    

    ここに新しいアレイはありません。既存の不変データへのポインタをコピーするだけです。

于 2012-02-24T19:35:01.790 に答える
0

彼らは違う。 a変更できない文字列リテラルを指します。ただし、bは指定された文字列で初期化される文字の配列です。が削除されたとすると、constの内容を変更できますb

于 2012-02-24T19:28:39.240 に答える
0

はい、違います。

"hello"文字列リテラル自体(および"goodbye")が不変であることは事実です。ただし、にアクセスしているときはb、元のにアクセスしていません"goodbye"。使用したコードは、文字列リテラルでbのみ初期化"goodbye"される完全に独立した配列を宣言しました。'b'は、元の文字列リテラルから完全に独立しています"goodbye"。あなたbはその文字列リテラルのコピーです。'b'が不変である唯一の理由はconst、宣言に明示的に含まれていることです。これを削除すると、通常のアレイと同様に、完全に変更可能になりconstます。b

'a'は、元の文字列リテラルを直接指すポインタです"hello"。もちろん、それは不変です。

于 2012-02-24T19:40:10.700 に答える
0

どちらのオプション不変ですが、文字列リテラルから作成されているためではありません。const変数宣言のキーワードのため、これらは不変です。

書くこともでき、リテラルchar c[] = "string_c";の可変コピー(名前付き)を作成します。cstring_c

の定数を削除する例では、状況によっては機能するように見えるb場合がありますが、標準に関する限り、それでも違法です。真に非定数であるオブジェクトのみを変更できます。

于 2012-02-24T19:44:10.680 に答える