Namespaces
Variants

strcat, strcat_s

ja.cppreference.net から
< c | string | byte
ヘッダ <string.h>
char* strcat( char* dest, const char* src );
で定義されています。 (1) (C99まで)
char* strcat( char* restrict dest, const char* restrict src );
(C99以降)
errno_t strcat_s(char* restrict dest, rsize_t destsz, const char* restrict src);
(2) (C11以降)
1) src が指すヌル終端バイト文字列のコピーを、dest が指すヌル終端バイト文字列の末尾に追加します。src[0] 文字が dest の末尾のヌル終端文字を置き換えます。結果のバイト文字列はヌル終端となります。
コピー先配列が src と dest の内容および終端のヌル文字を保持するのに十分な大きさでない場合、動作は未定義です。文字列が重なる場合、動作は未定義です。dest または src のいずれかがヌル終端バイト文字列へのポインタでない場合、動作は未定義です。
2) (1) と同じですが、コピー先配列の残りの部分(最後に書き込まれた文字から destsz まで)を未指定の値で上書きする可能性がある点と、以下のエラーが実行時に検出され、現在インストールされている 制約ハンドラ 関数を呼び出す点が異なります:
  • src または dest がヌルポインタである
  • destsz がゼロまたは RSIZE_MAX
  • より大きいdestsz の最初の dest
  • バイト内にヌル終端子がないdest の末尾の利用可能なスペースに src のすべての文字(ヌル終端子を含む)が収まらない場合、切り詰めが発生する
  • コピー元とコピー先の文字列の間で重なりが発生する
dest < strlen(dest)+strlen(src)+1 < が指す文字配列のサイズが destsz 未満である場合、動作は未定義です。言い換えれば、destsz の誤った値が差し迫ったバッファオーバーフローを露呈させることはありません。
すべての境界チェック付き関数と同様に、strcat_s は、__STDC_LIB_EXT1__ が実装によって定義され、ユーザーが __STDC_WANT_LIB_EXT1__ を整数定数 1 に定義してから <string.h> をインクルードした場合にのみ利用可能であることが保証されます。

引数

dest - 追加先のヌル終端バイト文字列へのポインタ
src - コピー元のヌル終端バイト文字列へのポインタ
destsz - 書き込む最大文字数。通常はコピー先バッファのサイズ

戻り値

1) dest
のコピーを返す2)dest[0] 成功時はゼロを返し、エラー時は非ゼロを返します。また、エラー時には dest にゼロを書き込みます(destsz がヌルポインタであるか、RSIZE_MAX がゼロまたはそれより大きい場合を除く)。

ノート

strcat は呼び出しごとに dest の末尾を探す必要があるため、strcat を使用して多数の文字列を1つに連結するのは非効率です。

strcat_s 効率を向上させるために、最後に書き込まれた文字から destsz までのコピー先配列を上書きすることが許可されています。マルチバイトブロックでコピーしてからヌルバイトをチェックする場合があります。

関数 strcat_s は BSD 関数 strlcat に似ていますが、以下の点が異なります。

  • strlcat コピー元の文字列をコピー先に収まるように切り詰める
  • strlcat strcat_s が行うすべてのランタイムチェックを実行しない
  • strlcat 失敗時にコピー先をヌル文字列に設定したり、ハンドラを呼び出したりして失敗を明確にしない。

strcat_s は潜在的なセキュリティリスクのために切り詰めを禁止していますが、境界チェック付きの strncat を使用して文字列を切り詰めることは可能です。

例

#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    char str[50] = "Hello ";
    char str2[50] = "World!";
    strcat(str, str2);
    strcat(str, " ...");
    strcat(str, " Goodbye World!");
    puts(str);

#ifdef __STDC_LIB_EXT1__
    set_constraint_handler_s(ignore_handler_s);
    int r = strcat_s(str, sizeof str, " ... ");
    printf("str = \"%s\", r = %d\n", str, r);
    r = strcat_s(str, sizeof str, " and this is too much");
    printf("str = \"%s\", r = %d\n", str, r);
#endif
}

出力例:

Hello World! ... Goodbye World!
str = "Hello World! ... Goodbye World! ... ", r = 0
str = "", r = 22

参考文献

  • C23 規格 (ISO/IEC 9899:2024):
  • 7.24.3.1 strcat 関数 (p: TBD)
  • K.3.7.2.1 strcat_s 関数 (p: TBD)
  • C17 規格 (ISO/IEC 9899:2018):
  • 7.24.3.1 strcat 関数 (p: TBD)
  • K.3.7.2.1 strcat_s 関数 (p: TBD)
  • C11 規格 (ISO/IEC 9899:2011):
  • 7.24.3.1 strcat 関数 (p: 364)
  • K.3.7.2.1 strcat_s 関数 (p: 617-618)
  • C99 規格 (ISO/IEC 9899:1999):
  • 7.21.3.1 strcat 関数 (p: 327)
  • C89/C90 規格 (ISO/IEC 9899:1990):
  • 4.11.3.1 strcat 関数

関連項目

2つの文字列の一定量の文字を連結する
(関数)
一方の文字列をもう一方にコピーする
(関数)
指定された区切り文字まで、一方のバッファをもう一方にコピーする
(関数)
用