【C言語】文字列を連結・結合する【strcatの危険性とsnprintfの安全性】C言語で文字列の連結を実現する方法としては、strcat/strncat関数を用いる方法が知られています。バッファオーバーフローの危険性があるため注意して利用する必要があります。複数の文字列を新たな文字列として結合したい場合にはsnprintf関数の利用が最適です。stncat関数とstrncat関数の危険性・安全策)。"abc"strcat関数は、第一引数に指定された文字列の末尾(ナル文字'\0'が最初に出現する位置)に、第二引数に指定された新たな文字列を追加する関数です。strncat関数の場合は第三引数に追加する文字列の長さを指定することができます。結合用の空配列を用いる場合には事前にゼロ初期化が必要となります。'\0';)、またはstrcpy関数を用いて文字列を先頭位置へとコピーする必要があります。'\0'}固定長の文字列を連結する場合(memcpy関数による連結)NULL終端されていない固定長の文字配列を連結する場合には、strcat関数やstrcpy関数を用いることができないため、代わりにmemcpy関数を用いる必要があります。"AaBb"memcpy関数の第一引数には書き込み先のバッファを指定します。第二引数には書き込む文字列、第三引数には書き込みたい長さを指定します。2や&s[2]という形で、書き込み開始位置のオフセットを明示する必要があります。memcpy関数はNULL終端を行わないため、必要に応じてナル文字('\0')による終端処理を行います。stncat関数とstrncat関数の危険性・安全策strcat関数はバッファオーバーランの危険性があるため注意して利用する必要があります。連結先文字列と連結元文字列の両サイズの合計が連結先文字列のバッファーサイズを上回った場合に、余計な書き込みが発生してしまいます。2バイト分余計に書き込まれてしまうより安全な対策方法としては、連結後のサイズを事前に計算し、安全な長さの場合にのみ実際の連結処理を行うようにすることです。printf("十分なバッファサイズが確保されていません");}なおstrncat関数はstrcat関数の安全版では無い点に注意が必要です。第三引数は書き込み可能な長さではなく、書き込み元の文字列の長さを表します。strncat関数を用いる場合には、余計に追加される終端NULL文字の分を考慮し、配列のバッファを大きめに確保したり、または第三引数の長さを一文字分小さめに指定したり、strcat関数の時と同様に連結後の文字列長さを事前計算したりする必要があります。#strncat関数の危険性と対策snprintf関数による文字列結合snprintf関数はフォーマット用の関数ですが、文字列の連結用途としても活用することができます。"ab"第一引数に書き込み先の配列、第二引数に書き込み可能な長さを指定します。第三引数にはprintf関数と同等のフォーマット文字列を指定します。第四引数以降には実際に連結したい文字列を指定します。第二引数に指定された長さを超えた書き込みは発生しません。書き込み先のバッファは常にNULL文字で終端処理されます。ちなみにsnprintf関数は様々な型のフォーマットが可能となっているため、数値との連結や、空白やカンマによる連結、3つ以上の文字列連結など、より柔軟な文字列連結が可能となっています。'-'}snprintf関数の特性により、書き込み先のバッファには自動的にナル文字('\0')が書き込まれるため注意してください。固定長の文字列を連結する場合(memcpy関数による連結))。連結元の文字列の長さを動的に指定する配列のサイズを動的に指定したい場合には、変換指定子の幅に*を指定し(%.*s)、実際の幅をsnprintf関数の実引数に指定します。バッファサイズ9が優先され'&'は切り捨てられるsnprintf関数の安全性・注意点snprintf関数の第三引数には書き込み先文字列のバッファサイズを指定することができるため、万が一想定外の長さの文字列を指定してしまっても、余計な書き込みによるバッファオーバーランが発生しません。バッファオーバーフローが発生しないただし、文字列連結時におけるsnprintf関数の利用は、あくまで万が一の場合の予防策に過ぎません。超過した分の文字列は暗黙の内に切り捨てられる事になるため、このことが逆に別の新たな問題やバグを引き起こすことに繋がる恐れがあります。stncat関数とstrncat関数の危険性・安全策」で紹介した例のように、連結後の長さと連結先のバッファサイズを事前にチェックすることが求められます。その際には、処理の目的を明確化するために、snprintf関数ではなくstncat関数/strncat関数を用いて文字列連結を行うのも良いでしょう。[])は、加算演算子(+)による文字列結合が行えません。C言語の文字列は配列やポインタで表現されているため、文字列だけ特別扱いというわけにはいかないのです。*')なお文字列リテラル同士であれば、両定数を並べるだけで連結が行われます。この連結はあくまでコンパイル時に行われるものです。";なお、C++の文字列型(std::string)は+演算子や+=演算子に対応しているため、文字列の連結や結合を行うことが可能となっています。次項を参考にしてください。std::stringを介した連結・結合C++スタイルの文字列型(std::string)を介することで、文字列同士の安全な連結処理や結合処理を実現することもできます。メモリの動的確保が発生する場合がありますが、自前で処理するよりは安全な方法となります。文字列の連結と結合c_strはC言語スタイルの文字列を参照するための関数です。c_str関数の戻り値の有効期限はstd::string型の一時変数の寿命に依存するため注意が必要です。c_strの結果を書き換えることはできません。std::stringオブジェクトの値や状態を変更した場合、c_strで取得していた文字列は不定なものとなります。*型の連結結果を永続的に保持したい場合は、文字列を手動でコピーする必要があります。