strncpy, strncpy_s
|
定義先ヘッダ
<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以降) |
src
が指す文字配列から(終端のヌル文字を含むが、ヌル文字以降の文字は含まない)最大
count
文字を
dest
が指す文字配列にコピーする。
count
が配列全体
src
がコピーされる前に到達した場合、結果の文字配列はnull終端されません。
src
から終端ナル文字をコピーした後、
count
に達していない場合、追加のナル文字が
dest
に書き込まれ、合計で
count
文字が書き込まれるまで続きます。
dest
または
src
が文字配列へのポインタでない場合(
dest
または
src
がnullポインタの場合を含む)、
dest
が指す配列のサイズが
count
より小さい場合、または
src
が指す配列のサイズが
count
より小さく、かつnull文字を含まない場合、動作は未定義です。
count
までパディングするために宛先配列にゼロを書き続けることはせず、終端ナル文字を書き込んだ後で停止します(ソースにナル文字が存在しなかった場合は、
dest
[
count
]
にナル文字を書き込んで停止します)。また、以下のエラーが実行時に検出され、現在設定されている
constraint handler
関数を呼び出します:
-
-
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 | - | 宛先バッファのサイズ |
戻り値
dest
のコピーを返す
dest
がnullポインタの場合、または
destsz
がゼロまたは
RSIZE_MAX
より大きい場合を除く)。また、宛先配列の残りの部分を未規定の値で上書きする可能性があります。
注記
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"; // null終端文字なし strncpy(dest, src, 5); // 5文字 'h', 'i', '\0', '\0', '\0' を 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); // 切り捨て: 2文字 'h', 'i' を 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); // r1 に 0 を書き込み、6文字を dst1 に書き込む printf("dst1 = \"%s\", r1 = %d\n", dst1,r1); // 'h','e','l','l','o','\0' を dst1 に書き込む char dst2[5], src2[7] = {'g','o','o','d','b','y','e'}; errno_t r2 = strncpy_s(dst2, 5, src2, 7); // コピーが宛先配列をオーバーフロー printf("dst2 = \"%s\", r2 = %d\n", dst2,r2); // 0以外を r2 に書き込み、'\0' を dst2[0] に書き込む char dst3[5]; errno_t r3 = strncpy_s(dst3, 5, src2, 4); // r3 に 0 を書き込み、5文字を dst3 に書き込む printf("dst3 = \"%s\", r3 = %d\n", dst3,r3); // 'g', 'o', 'o', 'd', '\0' を 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 strncpy関数 (p: 265)
-
- K.3.7.1.4 strncpy_s関数 (p: 447-448)
- C11標準 (ISO/IEC 9899:2011):
-
- 7.24.2.4 strncpy関数 (p: 363-364)
-
- K.3.7.1.4 strncpy_s関数 (p: 616-617)
- C99規格 (ISO/IEC 9899:1999):
-
- 7.21.2.4 strncpy関数 (p: 326-327)
- C89/C90標準 (ISO/IEC 9899:1990):
-
- 4.11.2.4 strncpy関数
関連項目
|
(C11)
|
文字列を別の文字列にコピーする
(関数) |
|
(C11)
|
バッファを別のバッファにコピーする
(関数) |
|
(dynamic memory TR)
|
指定されたサイズまでの文字列のコピーを割り当てる
(関数) |
|
C++ documentation
for
strncpy
|
|