Why does this code produce runtime issues:
char stuff[100];
strcat(stuff,"hi ");
strcat(stuff,"there");
but this doesn't?
char stuff[100];
strcpy(stuff,"hi ");
strcat(stuff,"there");
strcat
将查找空终止符,将其解释为字符串的结尾,并将新文本附加到那里,在此过程中覆盖空终止符,并在连接末尾写入一个新的空终止符。
char stuff[100]; // 'stuff' is uninitialized
空终止符在哪里? stuff
未初始化,因此它可能以 NUL 开头,或者它可能在其中的任何地方都没有 NUL。
在 C++ 中,您可以这样做:
char stuff[100] = {}; // 'stuff' is initialized to all zeroes
现在你可以做 strcat,因为 'stuff' 的第一个字符是空终止符,所以它会附加到正确的位置。
在 C 中,您仍然需要初始化“stuff”,这可以通过以下几种方式完成:
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 "
. 如果它没有找到它,它将跑出数组的末尾,并且可能会发生任意坏事(即行为未定义)。
避免该问题的一种方法是:
char stuff[100];
stuff[0] = '\0'; /* ensures stuff contains a valid string */
strcat(stuff, "hi ");
strcat(stuff, "there");
或者您可以初始化stuff
为一个空字符串:
char stuff[100] = "";
这将stuff
用零填充所有 100 个字节(增加的清晰度可能值得任何小的性能问题)。
因为stuff
在调用strcpy
. 声明后stuff
不是空字符串,是未初始化的数据。
strcat
将数据附加到字符串的末尾 - 即它在字符串中找到空终止符并在其后添加字符。未初始化的字符串不保证具有空终止符,因此strcat
可能会崩溃。
如果要按stuff
以下方式进行初始化,则可以执行 strcat 的:
char stuff[100] = "";
strcat(stuff,"hi ");
strcat(stuff,"there");
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;
}
正如您在此实现中看到的,除非初始化为正确的 c 字符串值,strlen(dest)
否则不会返回正确的字符串长度。dest
您可能很幸运拥有一个第一个值为 0 的数组char stuff[100];
,但您不应该依赖它。