マニュアル ページや Web サイトなどを紹介することもできますが、最終的に重要なのは C 標準そのものです。標準ランタイム ライブラリの一部として、使用法と動作は C99-§7.23.2.4 で次のように定義されています。
#include <string.h>
char *strncpy(char * restrict s1,
const char * restrict s2,
size_t n);
説明
このstrncpy
関数は、s2 が指す配列から s1 が指す配列に最大 n 文字 (ヌル文字に続く文字はコピーされません) をコピーします。重複するオブジェクト間でコピーが行われる場合、動作は未定義です。s2 が指す配列が n 文字より短い文字列である場合、合計 n 文字が書き込まれるまで、s1 が指す配列内のコピーにヌル文字が追加されます。
戻りstrncpy
値 関数は s1 の値を返し
ます。
ここには重要な暗黙の情報があります。最も重要なのは、ソース文字列の長さ (ヌル文字ターミネーターを含まない) が指定された宛先バッファー長以上である場合、宛先文字列をヌル文字で終了させないことですstrncpy()
) 。
さらに、標準で明確に指定されていますが (上記を参照)、ソース文字strncpy()
列n
の長さが宛先バッファ サイズ。これにより、次の避けられない結論が導き出されます。
API は常に、デスティネーション バッファが参照するアドレスに文字をstrncpy()
書き込みます。n
あなたの場合、target-buffer の幅はわずか 10 文字であるため、書き込み可能なメモリの定義済みの終わりを超えて 90 文字を追加で書き込み、未定義の動作の土地に足を踏み入れています。
この時点で、「それで何の役に立つの?」と自問する必要があります。間違いなく基本的なユースケースがあります。n
これにより、過去の文字をオーバーランしないという予測可能性を備えたターゲット バッファーに最大文字をコピーできますn
。限目。ただし、最終的には null で終わる文字列が必要なので、適切な使用法は次のとおりです。
char dst[ N ];
strncpy(dst, src, N-1);
dst[N-1] = 0;
ここで、 は文字N
単位のバッファのハード長で、dst
より大きいか等しい1
です。dst
動的に割り当てられたメモリ ポインターである可能性があることに注意してください。
char *dst = malloc( N * sizeof(char) );
strncpy(dst, src, N-1);
dst[N-1] = 0;
上記の場合、常にnull で終わる文字列が になりdst
ます。ソース文字列の長さが指定されたターゲット バッファの長さよりも小さい場合、strncpy()
source-chars-copied + tail-filled-null-characters の合計が と等しくなるまで、残りのバッファをヌル文字で埋めますn
。最終ステートメントは次のとおりです。冗長。ソース文字列の長さがターゲット バッファ長以上strncpy()
の場合、コピーを一度停止します。N-1
chars に達し、最後のステートメントはバッファの最後にヌル文字を設定します。これにより、元のソースの「カットダウン」プレフィックス文字列が生成されますが、最も重要なことは、ターミネータをスキャンする後の文字列 API 呼び出しでターゲット バッファの境界を超えないようにすることです。
上記の手法の有用性については、常に議論の余地があります。私は C++ の男なのでstd::string
、幸せな自分をこのすべての狂気から救います。しかし、現実src
は次のとおりです。時々あなたはしません。有用性は非常に状況に依存します。UI で文字列データを表示する場合、これは (おそらく) 問題になりません。重要なデータに使用する文字列をコピーする場合、partial-prefix-substring は受け入れられません。警察が「Joseph Johnson Jr.」に逮捕状を発行するとき、彼の父親 (「Joseph Johnson」) が刑務所に引きずり込まれたときに、逮捕状発行ソフトウェアの名前バッファーが 15 文字しか保持されていないため、説明する必要があります。 .dst
そうは言っても、セグメンテーションの誤りは次のステートメントに帰着します。
strncpy(s1.from_str,src, 100); // length parameter is wrong.
上記の太字のステートメントを思い出してください。strncpy()
n
. これは、上記のコードが常に100 文字をターゲット バッファーに書き込むことを意味します。この場合、幅は 10 文字しかないため、未定義の動作とker-boom の可能性があります。
ターゲット バッファーが固定長の文字配列である場合は、次の手順を実行してこれを修正します。
strncpy(s1.from_str,src, sizeof(s1.from_str)/sizeof(s1.from_str[0])-1);
s1.from_str[ sizeof(s1.from_str)/sizeof(s1.from_str[0])-1 ] = 0;
長さ `N 文字の動的文字列に対してこれを行う方法については、以前の使用法を参照してください。