http://www.cplusplus.com/reference/clibrary/cstring/strncpy/に関して、次の点についてstrncpy
言及しています。
宛先の末尾にヌル文字が暗黙的に追加されることはないため、ソース内のC文字列の長さがnum未満の場合にのみ、宛先はヌル終了されます。
この文はどういう意味ですか?
http://www.cplusplus.com/reference/clibrary/cstring/strncpy/に関して、次の点についてstrncpy
言及しています。
宛先の末尾にヌル文字が暗黙的に追加されることはないため、ソース内のC文字列の長さがnum未満の場合にのみ、宛先はヌル終了されます。
この文はどういう意味ですか?
これは、たとえば、ソース文字列が 20 文字に null ターミネータを加えたもので、strncpy
指定した文字数が 21 文字未満の場合、ターゲット文字列に null が追加されないことを意味します。
これは、動作方法によるものですstrncpy
。N が渡された長さの値である場合、正確に N バイトを書き込むことが保証されます。
ソース文字列 (sans null バイト) の長さがそれより短い場合、宛先領域に null が埋め込まれます。等しいかそれ以上の場合、宛先に null が追加されることはありません。
つまり、技術的には取得した C 文字列ではない可能性があります。これは、次のようなコードで解決できます。
char d[11]; // Have enough room for string and null.
strncpy (d, s, 10); // Copy up to 10 bytes of string, null the rest.
d[10] = '\0'; // Then append null manually in case s was too long.
11 バイト (配列インデックス 0..10) を割り当て、最大 10 (インデックス 0..9) までコピーしてから、11 番目 (インデックス 10) を null に設定します。
さまざまなサイズの文字列を 10 文字の領域に書き込むための 3 つの可能性を示す図を次に示します。strncpy (d, s, 10)
ここで.
はヌル バイトを表します。
s d
------------- ----------
Hello. Hello.....
Hello Fred. Hello Fred
Hello George. Hello Geor
2 番目と 3 番目のケースでは、null バイトが書き込まれないため、d
文字列として扱うと、結果に失望する可能性が高いことに注意してください。
文字列"foo"
には 3 文字 + 1 つの null ターミネータ ( として保存されます"foo\0"
) があり、合計の長さは 4 です。(またはそれより少ない数で) 呼び出した場合strncpy
、n=3
ターゲット文字列の末尾に null ターミネータは追加されませんが、コピーされます。のみ"foo"
。結果の文字列を出力しようとすると、文字列の終わりを知らせる null ターミネータがないため、未定義の動作が発生します。
これには細心の注意を払いn
、最大ソースよりも大きい値を渡すか、null ターミネータを自分で追加する必要があります。
つまり、ソース文字列の終端の null をコピーしますが、ソース文字列が宛先に収まらない場合は終端の null を追加しません。
の配列として格納された C 文字列char
は null で終了します。つまり、最後に余分な文字列が追加0
され、文字列の終わりを示し、後で文字列の長さを把握するために使用できます。したがって、文字列"hello"
はメモリ内で次のようになります。
char hello[] = {'h', 'e', 'l', 'l', 'o', 0};
通常、文字列をコピーするときは、文字もコピーするnull
必要があります。したがって、文字列バッファに必要なメモリは、その長さ + 1 です (例: (strlen(hello) + 1) * sizeof(char)
)。
関数strncpy
を使用すると、提供されたバッファーに収まる限り多くの文字のみをコピーできます。あなたが提供したバッファがその extra を保持するのに十分な大きさでない場合null
、それは追加されません。または、文字列が切り取られた場合、null で終了しません。
char hello[] = "hello"; // 5 characters, 6 bytes long
char hel[3];
strncpy(hel, hello, 3); // hel is {'h', 'e', 'l'}
strncpy
結果が有効な C 文字列ではない可能性があるため、を呼び出した後は常に注意する必要があります。文字列が null で終了していない場合、その長さを知ることは不可能であり、ほとんどの文字列操作関数は失敗するか、予期しないことを行います。
これは、num
コピー元バッファーからコピー先バッファーにバイトのみがコピーされることを意味します。そのため、ソース文字列の長さが より大きいか等しい場合num
、終端の NULL バイトはコピーされず、結果には危険な NULL 終端のバイトが含まれません。
代わりにstrlcpyを使用することをお勧めします。