strncat, strncat_s
提供: cppreference.com
<tbody>
</tbody>
<tbody class="t-dcl-rev t-dcl-rev-num ">
</tbody><tbody>
</tbody>
| ヘッダ <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)
- C99 standard (ISO/IEC 9899:1999):
- 7.21.3.2 The strncat function (p: 327-328)
- C89/C90 standard (ISO/IEC 9899:1990):
- 4.11.3.2 The strncat function
関連項目
(C11) |
2つの文字列を連結します (関数) |
(C11) |
文字列を別の文字列へコピーします (関数) |
strncat の C++リファレンス
| |