Namespaces
Variants

strncat, strncat_s

From cppreference.net
< c ‎ | string ‎ | byte
ヘッダーで定義 <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) 最大で count 文字を、null文字が見つかると停止しながら、 src が指す文字配列から、 dest が指すnull終端バイト文字列の末尾に追加します。文字 src [ 0 ] dest の末尾のnull終端文字を置き換えます。終端のnull文字は常に最後に追加されます(したがって、この関数が書き込む可能性のある最大バイト数は count + 1 です)。
宛先配列が dest src の最初の count 文字、および終端ナル文字の両方の内容を格納するのに十分な領域を持たない場合、動作は未定義です。ソースオブジェクトと宛先オブジェクトがオーバーラップする場合、動作は未定義です。 dest がナル終端バイト文字列へのポインタでない場合、または src が文字配列へのポインタでない場合、動作は未定義です。
2) (1) と同じですが、この関数は宛先配列の残りの部分(最後に書き込まれたバイトから destsz まで)を破壊する可能性があり、以下のエラーが実行時に検出され、現在インストールされている constraint handler 関数を呼び出す点が異なります:
  • src または dest がnullポインタである
  • destsz または count がゼロまたは RSIZE_MAX より大きい
  • dest の最初の destsz バイトにnull文字が存在しない
  • 切り捨てが発生する場合: count または src の長さ(いずれか小さい方)が、 dest のnull終端文字と 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 がnullポインタの場合、または 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 strncat関数 (p: 379)
  • K.3.7.2.2 strncat_s関数 (p: TBD)
  • C17規格 (ISO/IEC 9899:2018):
  • 7.24.3.2 strncat関数 (p: 265-266)
  • K.3.7.2.2 strncat_s関数 (p: 449-450)
  • C11規格 (ISO/IEC 9899:2011):
  • 7.24.3.2 strncat関数 (p: 364-365)
  • K.3.7.2.2 strncat_s関数 (p: 618-620)
  • C99規格 (ISO/IEC 9899:1999):
  • 7.21.3.2 strncat関数 (p: 327-328)
  • C89/C90標準 (ISO/IEC 9899:1990):
  • 4.11.3.2 strncat関数

関連項目

二つの文字列を連結する
(関数)
文字列を別の文字列にコピーする
(関数)
(C23)
一つのバッファを別のバッファにコピーし、指定された区切り文字の後で停止する
(関数)