strncpy, strncpy_s
From cppreference.com
| ヘッダー <string.h> で定義 |
||
| (1) | ||
| char *strncpy( char *dest, const char *src, size_t count ); |
(C99まで) | |
| char *strncpy( char *restrict dest, const char *restrict src, size_t count ); |
(C99以降) | |
| errno_t strncpy_s( char *restrict dest, rsize_t destsz, const char *restrict src, rsize_t count ); |
(2) | (C11 以降) |
1)
src で示される文字配列から、最大 count 文字を dest で示される文字配列にコピーします(終端ヌル文字を含むが、ヌル文字より後の文字は含まない)。src 配列全体がコピーされる前に count に達した場合、結果の文字配列はヌル終端されません。src から終端ヌル文字をコピーした後、count に達していない場合、合計 count 文字が書き込まれるまで、追加のヌル文字が dest に書き込まれます。 文字配列が重複している場合、
dest または src が文字配列へのポインタでない場合(dest または src がヌルポインタである場合を含む)、dest が指す配列のサイズが count より小さい場合、または src が指す配列のサイズが count より小さく、ヌル文字を含まない場合は、未定義の動作となります。2) (1) と同じですが、関数は
count までゼロで埋めることを継続せず、終端ヌル文字を書き込んだ後に停止します(ソースにヌル文字がない場合は、dest[count] に1つ書き込んでから停止します)。また、実行時に以下のエラーが検出され、現在インストールされている 制約ハンドラ 関数が呼び出されます。- `src` または `dest` がヌルポインタである場合
-
destszがゼロまたは RSIZE_MAX より大きい場合 -
countが RSIZE_MAX より大きい場合 -
countがdestsz以上で、destszが strnlen_s(src, count) 以下の場合。つまり、切り捨てが発生する場合 - ソース文字列と宛先文字列の間に重複が発生する場合
dest が指す文字配列のサイズが strnlen_s(src, destsz) より小さい場合(すなわち、destsz の値が不正確で、バッファオーバーフローの可能性が示されない場合)は未定義の動作となります。src が指す文字配列のサイズが strnlen_s(src, count) より小さい場合(すなわち、count の値が不正確で、バッファオーバーフローの可能性が示されない場合)は未定義の動作となります。- すべての境界チェック関数と同様に、
strncpy_sが利用可能であることは、実装によって __STDC_LIB_EXT1__ が定義され、ユーザーが <string.h> をインクルードする前に __STDC_WANT_LIB_EXT1__ を整数定数 1 として定義した場合にのみ保証されます。
目次 |
[編集] パラメータ
| dest | - | コピー先の文字配列へのポインタ |
| src | - | コピー元の文字配列へのポインタ |
| count | - | コピーする最大文字数 |
| destsz | - | 宛先バッファのサイズ |
[編集] 戻り値
1) `dest` のコピーを返します。
2) 成功した場合はゼロを返し、エラーの場合は非ゼロを返します。また、エラー時には、
dest がヌルポインタでないか、destsz がゼロまたは RSIZE_MAX より大きくない限り、dest[0] にゼロを書き込み、残りの宛先配列は未指定の値で上書きされる可能性があります。[編集] 注意
C11 DR 468 によって修正されたように、strncpy_s は、strcpy_s とは異なり、エラーが発生した場合にのみ宛先配列の残りを上書きすることが許可されています。
strncpy とは異なり、strncpy_s は宛先配列をゼロで埋めません。これは、境界チェック版に既存のコードを変換する際の一般的なエラーの原因です。
宛先バッファに収まるように切り捨てることはセキュリティリスクであり、strncpy_s にとっては実行時制約違反ですが、count に宛先配列のサイズから 1 を引いた値を指定することで、切り捨て動作を得ることが可能です。これにより、最初の count バイトがコピーされ、常にヌル終端子が追加されます: strncpy_s(dst, sizeof dst, src, (sizeof dst)-1);
[編集] 例
このコードを実行
#define __STDC_WANT_LIB_EXT1__ 1 #include <string.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> int main(void) { char src[] = "hi"; char dest[6] = "abcdef"; // no null terminator strncpy(dest, src, 5); // writes five characters 'h', 'i', '\0', '\0', '\0' to dest printf("strncpy(dest, src, 5) to a 6-byte dest gives : "); for (size_t n = 0; n < sizeof dest; ++n) { char c = dest[n]; c ? printf("'%c' ", c) : printf("'\\0' "); } printf("\nstrncpy(dest2, src, 2) to a 2-byte dst gives : "); char dest2[2]; strncpy(dest2, src, 2); // truncation: writes two characters 'h', 'i', to dest2 for (size_t n = 0; n < sizeof dest2; ++n) { char c = dest2[n]; c ? printf("'%c' ", c) : printf("'\\0' "); } printf("\n"); #ifdef __STDC_LIB_EXT1__ set_constraint_handler_s(ignore_handler_s); char dst1[6], src1[100] = "hello"; errno_t r1 = strncpy_s(dst1, 6, src1, 100); // writes 0 to r1, 6 characters to dst1 printf("dst1 = \"%s\", r1 = %d\n", dst1,r1); // 'h','e','l','l','o','\0' to dst1 char dst2[5], src2[7] = {'g','o','o','d','b','y','e'}; errno_t r2 = strncpy_s(dst2, 5, src2, 7); // copy overflows the destination array printf("dst2 = \"%s\", r2 = %d\n", dst2,r2); // writes nonzero to r2,'\0' to dst2[0] char dst3[5]; errno_t r3 = strncpy_s(dst3, 5, src2, 4); // writes 0 to r3, 5 characters to dst3 printf("dst3 = \"%s\", r3 = %d\n", dst3,r3); // 'g', 'o', 'o', 'd', '\0' to dst3 #endif }
実行結果の例
strncpy(dest, src, 5) to a 6-byte dst gives : 'h' 'i' '\0' '\0' '\0' 'f' strncpy(dest2, src, 2) to a 2-byte dst gives : 'h' 'i' dst1 = "hello", r1 = 0 dst2 = "", r2 = 22 dst3 = "good", r3 = 0
[編集] 参考文献
- C17標準 (ISO/IEC 9899:2018)
- 7.24.2.4 The strncpy function (p: 265)
- K.3.7.1.4 The strncpy_s function (p: 447-448)
- C11標準 (ISO/IEC 9899:2011)
- 7.24.2.4 The strncpy function (p: 363-364)
- K.3.7.1.4 The strncpy_s function (p: 616-617)
- C99標準 (ISO/IEC 9899:1999)
- 7.21.2.4 The strncpy function (p: 326-327)
- C89/C90標準 (ISO/IEC 9899:1990)
- 4.11.2.4 The strncpy function
[編集] 関連項目
| (C11) |
ある文字列を別の文字列にコピーする (関数) |
| (C11) |
あるバッファを別のバッファにコピーする (関数) |
| (動的メモリーTR) |
指定されたサイズまでの文字列のコピーを確保する (関数) |
| C++ ドキュメント (strncpy)
| |