名前空間
変種
操作

strncpy, strncpy_s

提供: cppreference.com
< c‎ | string‎ | byte
ヘッダ <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] にそれを書き込み、その後停止します)。 また、以下のエラーが実行時に検出され、現在設定されている制約ハンドラ関数を呼びます。
  • src または dest がヌルポインタ。
  • destsz または count がゼロまたは RSIZE_MAX より大きい。
  • countdestsz より大きいまたは等しいけれども 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 はコピー先配列をゼロで埋めません。 これは既存のコードを境界チェック版に変換するとき、よくある謝りの元になります。

コピー先バッファに収まるよう切り捨てることはセキュリティリスクになり、そのため 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"; // 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";
    int 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'};
    int 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];
    int 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

[編集] 参考文献

  • 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]