strncat, strncat_s
From 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` の誤った値は、差し迫ったバッファオーバーフローを露呈しません。`src` が指す文字配列のサイズが strnlen(src,count) よりも小さい場合、動作は未定義です。つまり、`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` は呼び出しごとに `dest` の末尾にシークする必要があるため、`strncat` を使用して多数の文字列を 1 つに連結するのは効率が悪いです。
宛先バッファに収まるように切り捨てることはセキュリティリスクであり、したがって `strncat_s` では実行時制約違反ですが、`count` を宛先配列のサイズから 1 を引いた値に指定することで、切り捨て動作を得ることができます。この場合、最初の `count` バイトがコピーされ、常にヌル終端子が追加されます: strncat_s(dst, sizeof dst, src, (sizeof dst)-strnlen_s(dst, sizeof dst)-1);
[編集] 例
このコードを実行
#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); // r4 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
[編集] 参考文献
- C23標準 (ISO/IEC 9899:2024)
- 7.26.3.2 The strncat function (p: 379)
- K.3.7.2.2 The strncat_s function (p: TBD)
- C17標準 (ISO/IEC 9899:2018)
- 7.24.3.2 The strncat function (p: 265-266)
- K.3.7.2.2 The strncat_s function (p: 449-450)
- C11標準 (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標準 (ISO/IEC 9899:1999)
- 7.21.3.2 The strncat function (p: 327-328)
- C89/C90標準 (ISO/IEC 9899:1990)
- 4.11.3.2 The strncat function
[編集] 関連項目
| (C11) |
2つの文字列を連結する (関数) |
| (C11) |
ある文字列を別の文字列にコピーする (関数) |
| (C23) |
指定された区切り文字で停止しながら、あるバッファを別のバッファにコピーする (関数) |
| C++ ドキュメント (strncat)
| |