名前空間
変種
操作

strncpy, strncpy_s

提供: cppreference.com
< c‎ | string‎ | byte
ヘッダ <string.h> で定義
(1)
char*strncpy(char*dest, constchar*src, size_t count );
(C99未満)
char*strncpy(char*restrict dest, constchar*restrict src, size_t count );
(C99以上)
errno_t strncpy_s(char*restrict dest, rsize_t destsz,
                  constchar*restrict src, rsize_t count);
(2) (C11以上)
1)src の指す文字配列から最初のヌル文字まで最大 count 個の文字を dest の指す文字配列にコピーします。
dest の残りはゼロクリアされます (性能の懸念があるかもしれません)。
src の最初の count 個の文字がヌルでない場合、 dest はヌル終端されません!
文字配列がオーバーラップしている場合、 dest または src が文字配列を指すポインタでない場合 (dest または src がヌルポインタの場合も含みます)、 dest の指す配列のサイズが count より小さい場合、または src の指す配列のサイズが count より小さくヌル文字を含まない場合、動作は未定義です。
2)src の指す文字配列から最初のヌル文字まで最大 count 個の文字を dest の指す文字配列にコピーします。
その後、ヌル終端を追加します。 そのため dest は必ずヌル終端文字列になります。
エラーが検出された場合、 dest の残りは未規定の値になります。
以下のエラーが実行時に検出され、現在設定されている制約ハンドラ関数を呼びます。
  • src または dest がヌルポインタ。
  • destsz または count がゼロまたは RSIZE_MAX より大きい。
  • destszstrnlen_s(src, count) より小さいまたは等しい。 別の言い方をすると、切り捨てが発生する。
  • コピー元とコピー先の文字列間でオーバーラップが発生する。
dest の指す文字配列のサイズ < strnlen_s(src, destsz) <= destsz の場合、動作は未定義です。 別の言い方をすると、誤った destsz の値は切迫したバッファオーバーフローを露呈しません。 src の指す文字配列のサイズ < strnlen_s(src, count) < destsz の場合、動作は未定義です。 別の言い方をすると、誤った count の値は切迫したバッファオーバーフローを露呈しません。
すべての境界チェック付き関数と同様に、 strncpy_s__STDC_LIB_EXT1__ が処理系によって定義されていて、 <string.h> をインクルードする前にユーザが __STDC_WANT_LIB_EXT1__ を整数定数 1 に定義した場合にのみ、利用可能であることが保証されます。

目次

[編集]引数

dest - コピー先の文字配列を指すポインタ
src - コピー元の文字配列を指すポインタ
count - コピーする最大文字数
destsz - コピー先バッファのサイズ

[編集]戻り値

1)dest のコピーを返します。
2) 成功した場合はゼロを返します。 エラーが発生した場合は非ゼロを返します。 また、エラーの場合は dest[0] にゼロを書き込み (dest がヌルポインタでなく、 destsz がゼロでなく RSIZE_MAX より大きくなければ)、コピー先配列の残りを未規定の値で上書きする可能性があります。

[編集]ノート

C11 後の DR 468 で訂正されたように、 strncpy_sstrcpy_s と異なり、エラーが発生した場合にのみ、コピー先配列の残りを上書きすることが認められています。

strncpy と異なり、 strncpy_s はヌル終端文字列関数であり、コピー先配列をゼロクリアしません。 これは既存のコードを Annex K 版に変換するときのよくある誤りの元になります。

コピー先バッファに収まるよう切り捨てることはセキュリティリスクになり、そのため strncpy_s に対する実行時制約違反になりますが、コピー先配列のサイズより1小さい count を指定することにより、切り捨て動作を得ることが可能であり、最初の 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>   int main(void){char src[]="hi";char dest[6]="abcdef";// ヌル終端なし。 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";int r1 = strncpy_s(dst1, 6, src1, 100);// 6個の文字 'h','e','l','l','o','\0' を dst1 に書き込みます。printf("dst1 = \"%s\", r1 = %d\n", dst1,r1);// r1 は 0 になります。   char dst2[5], src2[7]={'g','o','o','d','b','y','e'};int r2 = strncpy_s(dst2, 5, src2, 7);// コピー先配列のオーバーフロー。printf("dst2 = \"%s\", r2 = %d\n", dst2,r2);// '\0' が dst2[0] に書き込まれ、 r2 は非ゼロになります。   char dst3[5];int r3 = strncpy_s(dst3, 5, src2, 4);// 5個の文字 'g', 'o', 'o', 'd', '\0' を dst3 に書き込みます。printf("dst3 = \"%s\", r3 = %d\n", dst3,r3);// r3 は 0 になります。#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

[編集]参考文献

  • C11 standard (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 standard (ISO/IEC 9899:1999):
  • 7.21.2.4 The strncpy function (p: 326-327)
  • C89/C90 standard (ISO/IEC 9899:1990):
  • 4.11.2.4 The strncpy function

[編集]関連項目

文字列を別の文字列へコピーします
(関数)[edit]
バッファを別のバッファへコピーします
(関数)[edit]
(dynamic memory TR)
指定されたサイズまで文字列のコピーを確保します
(関数)[edit]
close