web-dev-qa-db-ja.com

constなしでCスタイルの文字列を宣言するのは悪いですか?もしそうなら、なぜですか?

C++でこれを行う

char* cool = "cool";

コンパイルは正常に行われますが、警告が表示されます。

文字列定数からchar *への非推奨の変換

私はstd::stringでCスタイルの文字列を意図的に使用することは決してありませんが、念のために次の質問をします。

const修飾子なしでCスタイルの文字列を宣言するのは悪い習慣ですか?もしそうなら、なぜですか?

63
Coffee Maker

はい、この宣言は、次のような文字列リテラルへの書き込みによって未定義の動作を誤って引き起こす多くの方法を許可するため、悪い習慣です。

cool[0] = 'k';
strcpy(cool, "oops");

一方、これはcharの非const配列を割り当てるため、まったく問題ありません。

char cool[] = "cool";
59
aschepler

はい。C++では、const char *またはconst char [N]型の変数を持つ文字列リテラルを常に参照する必要があります。これは、新しいCコードを記述するときのベストプラクティスでもあります。

文字列リテラルは、可能な場合は読み取り専用メモリに保存されます。それらのタイプは適切にconst修飾されています。 Cは、C++ではなく、コンパイラーがchar [N]型を与える下位互換性のいぼを含みますが、それらは読み取り専用で保存されますメモリ。これは、文字列リテラルがconst修飾子よりも古いためです。 constは、現在「C89」と呼ばれているものの準備段階で発明されました。以前の「K&R」形式の言語にはありませんでした。

一部のCコンパイラには、下位互換性wartが無効になっているオプションモードが含まれており、char *foo = "...";はC++と同じまたは同様の診断を取得します。 GCCはこのモードを-Wwrite-stringsと綴ります。新しいコードにはこれを強くお勧めします。ただし、古いコードに対して有効にすると、ほとんどメリットがないために大量のカットワークが必要になります。

16
zwol

これは悪いです。すごく悪いですね。これまでは、C++ 11でこれを行うことはできません。

文字列リテラルのメモリの変更は未定義の動作です。

14
milleniumbug

最初、 char* cool = "cool";は標準C++ではありません。文字列リテラルのタイプはconst char[n]。したがって、上記のコード行はconst-correctnessを壊し、コンパイルすべきではありません。 GCCなどの一部のコンパイラはこれを許可しますが、Cからのホールドオーバーであるため警告を発行します。MSVCはエラーであるため、エラーを発行します。

第二に、コンパイラを動作させてみませんか? constとマークされている場合、誤って変更しようとするとNiceコンパイラエラーが発生します。そうしないと、非常に厄介な実行時エラーが発生する可能性があり、これを見つけるのははるかに困難です。

13
NathanOliver

文字列定数はバイナリごとに1回しか含まれない可能性があるため(キーワード:stringtable、.strtab)。例えば。に

char *cool = "cool";
char *nothot = "cool";

両方の変数は同じメモリ位置を指すことができます。それらの一方の内容を変更すると、他方も変更される可能性があるため、

strcpy(nothot, "warm");

coolは「ウォーム」になります。

要するに、それは未定義の振る舞いです。

7
ensc

これは文字列リテラルです。したがって、メモリは読み取り専用セクションに配置される可能性があるため、定数である必要があります。あなたが持っている場合 char cool[] = "cool";その後、それは問題ではありません、メモリはあなたのものです。

6
KIIV

char * cool = "cool"

「クール」は、関数間で共有される読み取り専用ブロック(通常はデータセグメント)に格納されます。ポイントcoolで文字列 "cool"を変更しようとすると、プログラムの実行中にセグメントエラーなどのエラーが発生します。 const char* cool = "cool"を使用する場合、文字列を変更しようとすると、コンパイル時にエラーが発生します。
詳細については、このページをお読みください http://www.geeksforgeeks.org/storage-for-strings-in-c/

2
zhangke

(特に文字列リテラルを使用した場合)文字列のconstを書くことは良い習慣ですが、Cでは違いはほとんどありませんが、c ++では警告がスローされますが、cでは警告がありません。 cとして.cとしてc ++ですので、そのような点では注意してください。そうでない場合は、文字列の場合にconstを使用することをお勧めします。読み取り専用メモリ内。

0
Noshiii