このコードが実行時の問題を引き起こす理由:
char stuff[100];
strcat(stuff,"hi ");
strcat(stuff,"there");
しかし、これはそうではありませんか?
char stuff[100];
strcpy(stuff,"hi ");
strcat(stuff,"there");
strcat
はヌルターミネータを探し、それを文字列の終わりとして解釈し、そこに新しいテキストを追加し、プロセス内のヌルターミネータを上書きし、最後に新しいヌルターミネータを書き込みます。連結。
char stuff[100]; // 'stuff' is uninitialized
Nullターミネーターはどこにありますか? stuff
は初期化されていないため、NULで始まるか、NULがどこにも含まれていない可能性があります。
C++では、これを行うことができます。
char stuff[100] = {}; // 'stuff' is initialized to all zeroes
これで、 'cat'の最初の文字がヌルターミネータであるため、strcatを実行できるようになり、正しい場所に追加されます。
Cでは、まだいくつかの方法で「もの」を初期化する必要があります。
char stuff[100]; // not initialized
stuff[0] = '\0'; // first character is now the null terminator,
// so 'stuff' is effectively ""
strcpy(stuff, "hi "); // this initializes 'stuff' if it's not already.
最初のケースでは、stuff
にゴミが含まれています。 strcat
では、宛先とソースの両方に適切なヌル終了文字列が含まれている必要があります。
strcat(stuff, "hi ");
stuff
をスキャンして、終了する'\0'
文字、コピーを開始する場所"hi "
。それが見つからない場合、配列の最後から実行され、任意の悪いことが起こる可能性があります(つまり、動作は未定義です)。
問題を回避する1つの方法は次のとおりです。
char stuff[100];
stuff[0] = '\0'; /* ensures stuff contains a valid string */
strcat(stuff, "hi ");
strcat(stuff, "there");
または、stuff
を空の文字列に初期化できます。
char stuff[100] = "";
これにより、stuff
の100バイトすべてがゼロで埋められます(明確さの向上は、パフォーマンスの小さな問題に見合う価値があります)。
Strcatは、既存の文字列に文字列を追加します。文字列配列が空の場合、文字列の末尾(_'\0'
_)を見つけられず、実行時エラーが発生します。
Linuxのマニュアルページによると、単純なstrcatは次のように実装されています。
_ char*
strncat(char *dest, const char *src, size_t n)
{
size_t dest_len = strlen(dest);
size_t i;
for (i = 0 ; i < n && src[i] != '\0' ; i++)
dest[dest_len + i] = src[i];
dest[dest_len + i] = '\0';
return dest;
}
_
この実装でわかるように、dest
がc文字列値を修正するために初期化されない限り、strlen(dest)
は正しい文字列長を返しません。 _char stuff[100];
_に最初の値がゼロの配列があると幸運になるかもしれませんが、それに頼るべきではありません。
stuff
がstrcpy
を呼び出す前に初期化されていないためです。宣言stuff
は空の文字列ではないため、初期化されていないデータです。
strcat
は、文字列の末尾にデータを追加します。つまり、文字列内でヌルターミネータを見つけ、その後に文字を追加します。初期化されていない文字列は、nullターミネータを持つように保証されていないため、strcat
がクラッシュする可能性があります。
以下のようにstuff
を初期化する場合、strcatを実行できます。
char stuff[100] = "";
strcat(stuff,"hi ");
strcat(stuff,"there");