web-dev-qa-db-ja.com

C ++の文字列が通常「\ 0」で終了するのはなぜですか?

多くのコードサンプルでは、​​通常、'\0'このような新しいchar配列を作成した後:

string s = "JustAString";
char* array = new char[s.size() + 1];
strncpy(array, s.c_str(), s.size());
array[s.size()] = '\0';

なぜ'\0' ここに?

17

質問のタイトルはC文字列を参照しています。 C++ std::stringオブジェクトの処理方法はstandard C stringsとは異なります。\0は、C文字列を使用する場合、およびここではstringという用語を使用していますが、これは標準のC文字列を指します。

\0はCでは文字列ターミネーターとして機能します。これはnull文字、または[〜#〜] nul [〜#として知られています〜]。これは、文字列を処理するコード-標準ライブラリだけでなく、独自のコード-文字列の終わりがどこにあるかを通知します。良い例は、文字列の長さを返すstrlenです。

次のようにして定数文字列を宣言すると、

const char *str = "JustAString";

次に、\0が自動的に追加されます。配列の例のように非定数文字列を管理する他のケースでは、自分で処理する必要がある場合があります。 ドキュメントのstrncpy は、例で使用されている良い例です。strncpyはnull終了文字をコピーしますexcept指定された長さに達する前に文字列全体がコピーされます。そのため、strncpyとnullターミネーターの冗長割り当てが組み合わされていることがよくあります。 strlcpyおよびstrcpy_sは、このケースの処理を怠ることから生じる潜在的な問題に対処するために設計されました。

特定の例では、array[s.size()] = '\0';はそのような冗長性の1つです。arrayのサイズはs.size() + 1であり、strncpys.size()文字をコピーしているため、関数は\0

標準のC文字列ユーティリティのドキュメントには、そのようなnullターミネータを含めるように注意する必要がある場合が示されています。ただし、ドキュメントを注意深く読んでください。strncpyと同様に、詳細が見過ごされやすく、バッファオーバーフローが発生する可能性があります。

42
pb2q

'\ 0'はNULL終了文字です。文字配列にそれがなく、strcpyを実行しようとすると、バッファオーバーフローが発生します。多くの関数は、メモリの読み取りまたは書き込みを停止する必要があるタイミングを知るために、この関数に依存しています。

6
evanmcdonnal
strncpy(array, s.c_str(), s.size());
array[s.size()] = '\0';

ここで '\ 0'を使用する必要があるのはなぜですか?

2行目はスペースの無駄です。 strncpyは、使用方法がわかっている場合、すでにnull終端を追加しています。コードは次のように書き直すことができます。

strncpy(array, s.c_str(), s.size()+1);

strncpyは一種の奇妙な関数で、最初のパラメーターが3番目のパラメーターのサイズの配列であると想定しています。したがって、文字列をコピーした後にスペースが残っている場合にのみ、null終端をコピーします。

この場合はmemcpy()を使用することもできますが、コードの直感性が低下する可能性がありますが、多少効率が向上します。

4
Lundin

Cでは、文字列をchar(またはw_char)の配列で表し、特殊文字を使用して文字列の終わりを示します。文字列の長さを配列のインデックス0に格納するPascalとは対照的に(したがって、文字列には文字数にハードリミットがあります)、理論的にの数に制限はありません。文字列(文字の配列として表される)がCで持つことができる文字.

特殊文字は、Cのデフォルトライブラリおよびその他のライブラリのすべての関数でNULであることが期待されています。文字列の正確な長さに依存するライブラリ関数を使用する場合は、文字列をNULで終了する必要があります。独自の終了文字を完全に定義できますが、文字列(文字の配列として)を含むライブラリ関数が期待どおりに機能せず、あらゆる種類のエラーが発生することを理解する必要があります。

与えられたコードスニペットでは、割り当てられた配列にごみデータがあるかどうかわからないため、終了文字を明示的にNULに設定する必要があります。大きなコードでは、文字の配列の初期化が表示されない場合があるため、これも良い方法です。

2
nhahtdh