strcatは、ある文字列に別の文字列を連結 (concatenate) するC言語関数である。 標準Cライブラリの文字列操作関数群が宣言されているヘッダーファイル string.h に含まれる。

書式 編集

#include <string.h>
char *strcat(char *s1, const char *s2);

機能 編集

s2が指す文字列を、s1が指す配列の最後に連結する。戻り値は、s1の値である。また、コピー先とコピー元が重なる場合の動作は未定義とする。

実装例 編集

char *StrCat(char *s1, const char *s2)
{
    char *p = s1;
    while(*s1++);           /* s1を最後まで進める */
    while(*s1++ = *s2++);   /* s2をコピーする */
    return p;
}

バッファオーバーランの危険性と対策 編集

strcatは、先程示した実装例を見ても分かる通り、s1の容量については一切関知しない。よって、s1の指す配列の範囲を越えて、s2が書き込まれてしまうバッファオーバーランの恐れがある。バッファオーバーランによってメモリが破壊されたり、プログラムが異常動作したり、クラッシュしたりする危険性がある。簡単な対策として、事前に領域長計算を実行する例を示す。

char s1[80] = "filename";
const size_t bufsize = sizeof(s1); /* 固定長char配列の要素数を求める */
const size_t s1len = strlen(s1);
const char* s2 = ".exe";
const size_t s2len = strlen(s2);
if (s1len + s2len + 1 <= bufsize) /* 1は終端NUL文字用 */
{
    memcpy(s1 + s1len, s2, s1len + s2len + 1);
    /* 以下でも可能だが、さらに冗長となるだけで意味はない。 */
    /*strcat(s1, s2);*/
    /*strncat(s1, s2, s2len);*/
}

strlenで文字列の長さを事前に取得しているので、もはやstrcatを使用する必要はなく、memcpyで十分となる。

上の例では、事前にchar型配列s1全体のバッファサイズすなわち要素数と、使用済み領域の長さおよび書き込みに必要な領域の長さを比較することによって、配列の空きの容量を超えた書き込み(バッファオーバーラン)を防ぐことができる。なお、さらに異常系や汎用目的を考慮するならば、s1の内容が未初期化で終端NUL文字が含まれていない場合や、s1len + s2len + 1算術オーバーフローを起こしてしまう場合への対処も必要となってくる。

字数制限付き文字列連結関数としてstrncatも存在するが、書き込み先のバッファサイズを指定できるわけではないので、やはりstrcat同様の危険性を持つことに変わりはない。

代替として、標準ライブラリの一部ではないがstrlcatやstrcat_sを使用することのできる処理系もある。 そのほか、単純な文字列連結用途としてはややオーバースペックではあるが、snprintfを使用する方法もある。

関連項目 編集

外部リンク 編集