0

過去に私は Visual Studio 2010/2013/2015 を使用しており、この構文は可能でした:

char* szString = "This works!";

g++ をインストールし、SlickEdit を IDE として使用しているため、コーディングのライフスタイルを Linux に移行することにしました。

その言葉はもう通用しないようです。誰でも理由を述べてもらえますか?

ただし、これは機能します:

char strString[] = "This works!";

エラーはc ++ 11のものです。

なぜこれが起こるのか誰にも分かりますか?それを修正する方法ではなく、私のワークスペースには c++11 コンパイラをインストールする方法がないため、コンパイラの動作の背景に何か関係があるかどうかに興味があります。コードの最初の行について私が知っていることは、スタック上に定数変数を作成し、その ESP の値に向けて設定する新しいポインターを作成することですが、2 行目では、定数変数の文字数をカウントしてから結果として最後に null ターミネータを設定します。

ああ、もう1つ->最初のタイプが{char * &}で、2番目のタイプが{char(*) [12]であるため、最初のタイプがGCC/GPPで設定されている方法にも違いがあるようです[12] }、それについても説明はありますか?ありがとう!

4

2 に答える 2

6

リテラルを記述する"text"と、そのテキストはコンパイルされたプログラム イメージのどこかに含まれます。プログラム イメージは通常、セキュリティ上の理由から、最近のオペレーティング システムでは書き込み保護されたメモリに配置されます。

char* someString = "text";おそらく書き込み保護されているプログラム イメージ内の文字列へのポインターを宣言します。このポインターを非 const として宣言する機能は、C とのソース互換性を維持するために C++11 まで含まれていた機能でしたsomeString。それでも未定義の動作が発生します。この後方互換性機能は C++11 で削除されました。 someStringconst へのポインターとして宣言する必要がありますconst char* someString = "text";。をキャストすることはできますがconst、指している値に書き込もうとすると、constconst 以外にキャストした値と同じ未定義の動作が発生します。

char someString[] = "text";動作が異なります。"text"これにより、文字列がプログラムのコード メモリからデータ メモリ内の配列にコピーされます。に似ている

char someString[5];
strcpy(someString, "text");

はプログラムのデータ メモリ内の配列であるためsomeString、書き込みは問題なく、const で修飾する必要はありません。

于 2016-07-10T17:30:17.950 に答える
2

標準によると: 付属書 C (互換性)

C1.1 2.14.5 節:

変更: 文字列リテラルが const になりました

文字列リテラルの型が「char の配列」から「const char の配列」に変更されました。char16_t 文字列リテラルの型を「何らかの整数型の配列」から「const char16_t の配列」に変更します。char32_t 文字列リテラルの型は、「何らかの整数型の配列」から「const char32_t の配列」に変更されます。</p>

ワイド文字列リテラルの型が「wchar_t の配列」から「const wchar_t の配列」に変更されました。</p>

理論的根拠: これにより、不適切なオーバーロードされた関数の呼び出しが回避されます。この関数は、引数を変更できることを期待している可能性があります。

実際、C++ 標準 2.14.5.8 には次のように書かれています。

通常の文字列リテラルと UTF-8 文字列リテラルは、ナロー文字列リテラルとも呼ばれます。ナロー文字列リテラルの型は「n const char の配列」です。ここで、n は以下で定義されている文字列のサイズであり、静的な保存期間があります。

これにより、そのような文字列はさまざまな特別な処理を受けることもできます。コンパイラ/リンカーは、コンパイル単位全体で文字列の重複を排除することを選択でき (msvc 用語での文字列プーリング)、それらをデータ セクションに格納し、メモリのみを読み取ることができます。

2.14.5.12

すべての文字列リテラルが異なる (つまり、重複しないオブジェクトに格納される) かどうかは実装定義です。文字列リテラルを変更しようとした場合の影響は未定義です。

これchar* x = "hello world";は、初期の C からの C++ の継承への逆戻りです。Visual Studio は、独自のライブラリに重い荷物があるため、これをサポートしています。

于 2016-07-10T18:17:43.133 に答える