为什么我首先要在strcat()之前使用strcpy()?
为什么此代码会产生运行时问题:
char stuff[100]; strcat(stuff,"hi "); strcat(stuff,"there");
但这不是吗?
char stuff[100]; strcpy(stuff,"hi "); strcat(stuff,"there");
strcat
将查找null-terminator,将其解释为字符串的结尾,并在其中附加新文本,覆盖进程中的null-terminator,并在连接结束时写入新的null-terminator。
char stuff[100]; // 'stuff' is uninitialized
空终止符在哪里? stuff
是未初始化的,所以它可能从NUL开始,或者它可能没有NUL在其中任何地方。
在C ++中,您可以这样做:
char stuff[100] = {}; // 'stuff' is initialized to all zeroes
现在你可以做strcat,因为’stuff’的第一个字符是null-terminator,所以它会附加到正确的位置。
在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
要求目标和源都包含正确的以null结尾的字符串。
strcat(stuff, "hi ");
将搜索终止'\0'
字符的内容,它将开始复制"hi "
。 如果它没有找到它,它将在数组的末尾运行,并且可能发生任意不好的事情(即,行为未定义)。
避免这个问题的一种方法是这样的:
char stuff[100]; stuff[0] = '\0'; /* ensures stuff contains a valid string */ strcat(stuff, "hi "); strcat(stuff, "there");
或者你可以将stuff
初始化为空字符串:
char stuff[100] = "";
这将用零填充所有100字节的stuff
(增加的清晰度可能值得任何小的性能问题)。
因为在调用strcpy
之前, stuff
是未初始化的。 声明后的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; }
正如您在此实现中所看到的,除非将dest
初始化为正确的c字符串值,否则strlen(dest)
将不会返回正确的字符串长度。 你可能很幸运,在char stuff[100];
有一个第一个值为零的数组char stuff[100];
,但你不应该依赖它。
另外,我建议不要使用strcpy
或strcat
因为它们可能导致一些意想不到的问题。
使用strncpy
和strncat
,因为它们有助于防止缓冲区溢出。