strncat, strncat_s
提供: cppreference.com
ヘッダ <string.h> で定義
|
||
(1) | ||
char *strncat( char *dest, const char *src, size_t count ); |
(C99未満) | |
char *strncat( char *restrict dest, const char *restrict src, size_t count ); |
(C99以上) | |
errno_t strncat_s(char *restrict dest, rsize_t destsz, const char *restrict src, rsize_t count); |
(2) | (C11以上) |
1)
src
の指す文字配列から最大 count
文字を dest
の指すヌル終端バイト文字列の末尾に追加します。 ヌル文字が見つかった場合は停止します。 文字 src[0] が dest
の末尾のヌル終端を置き換えます。 終端のヌル文字は常に末尾に追加されます (そのため書き込まれる可能性のある最大文字数は count+1 になります)。 コピー先配列が
dest
と src
の最初の count
文字と終端のヌル文字を合わせた内容に対して十分な空間がない場合、動作は未定義です。 コピー元とコピー先がオーバーラップしている場合、動作は未定義です。 dest
がヌル終端バイト文字列を指すポインタでない、または src
が文字配列を指すポインタでない場合、動作は未定義です。2) (1) と同じですが、コピー先配列の残り (書き込まれた最後の文字から
destsz
まで) を上書きするかもしれず、以下のエラーを実行時に検出し、現在設定されている制約ハンドラ関数を呼びます。
-
src
またはdest
がヌルポインタ。 -
destsz
またはcount
がゼロまたは RSIZE_MAX より大きい。 -
dest
の先頭destsz
バイトにヌル文字がない。 - 切り捨てが発生する。 つまり
count
またはsrc
の長さいずれか小さい方がdest
のヌル終端とdestsz
の間の利用可能な空間を超える。 - コピー元とコピー先の文字列間でオーバーラップが発生する。
-
dest
の指す文字配列のサイズ < strnlen(dest,destsz)+strnlen(src,count)+1 < destsz
の場合、動作は未定義です。 別の言い方をすると、誤った destsz
の値は切迫したバッファオーバーフローを露呈しません。 src
の指す文字配列のサイズ < strnlen(src,count) < destsz
の場合、動作は未定義です。 別の言い方をすると、誤った count
の値は切迫したバッファオーバーフローを露呈しません。
- すべての境界チェック付き関数と同様に、
strncat_s
は __STDC_LIB_EXT1__ が処理系によって定義されていて、<string.h>
をインクルードする前にユーザが __STDC_WANT_LIB_EXT1__ を整数定数 1 に定義した場合にのみ、利用可能であることが保証されます。
目次 |
[編集] 引数
dest | - | 追加先のヌル終端バイト文字列を指すポインタ |
src | - | コピー元の文字配列を指すポインタ |
count | - | コピーする最大文字数 |
destsz | - | コピー先バッファのサイズ |
[編集] 戻り値
1)
dest
のコピーを返します。2) 成功した場合はゼロを返します。 エラーが発生した場合は非ゼロを返します。 また、エラー場合は dest[0] にゼロを書き込みます (
dest
がヌルポインタでなく、 destsz
がゼロでなく RSIZE_MAX より大きくなければ)。[編集] ノート
コピー先バッファに収まるよう切り捨てることはセキュリティリスクになり、そのため strncat_s
に対する実行時制約違反になりますが、コピー先配列のサイズより1小さい count
を指定することにより、切り捨て動作を得ることが可能であり、最初の count
バイトをコピーしていつものようにヌル終端を追加します (strncat_s(dst, sizeof dst, src, (sizeof dst)-strnlen_s(dst, sizeof dst)-1);)。
[編集] 例
Run this code
#define __STDC_WANT_LIB_EXT1__ 1 #include <string.h> #include <stdio.h> #include <stdlib.h> int main(void) { char str[50] = "Hello "; char str2[50] = "World!"; strcat(str, str2); strncat(str, " Goodbye World!", 3); puts(str); #ifdef __STDC_LIB_EXT1__ set_constraint_handler_s(ignore_handler_s); char s1[100] = "good"; char s5[1000] = "bye"; int r1 = strncat_s(s1, 100, s5, 1000); // r1 is 0, s1 holds "goodbye\0" printf("s1 = %s, r1 = %d\n", s1, r1); char s2[6] = "hello"; int r2 = strncat_s(s2, 6, "", 1); // r2 is 0, s2 holds "hello\0" printf("s2 = %s, r2 = %d\n", s2, r2); char s3[6] = "hello"; int r3 = strncat_s(s3, 6, "X", 2); // r3 is non-zero, s3 holds "\0" printf("s3 = %s, r3 = %d\n", s3, r3); // the strncat_s truncation idiom: char s4[7] = "abc"; int r4 = strncat_s(s4, 7, "defghijklmn", 3); // r is 0, s4 holds "abcdef\0" printf("s4 = %s, r4 = %d\n", s4, r4); #endif }
出力例:
Hello World! Go s1 = goodbye, r1 = 0 s2 = hello, r2 = 0 s3 = , r3 = 22 s4 = abcdef, r4 = 0
[編集] 参考文献
- C11 standard (ISO/IEC 9899:2011):
- 7.24.3.2 The strncat function (p: 364-365)
- K.3.7.2.2 The strncat_s function (p: 618-620)