如果使用相同的数组作为两个参数,strcat()崩溃

char r[40]; strcpy(r,"abcdef"); strcat(r,r); 

我的程序在第三行崩溃了吗?

替换strcat(r,r); by strcat(r,“abcdef”); 虽然工作正常….为什么?

strcat()从输入读取并将其复制到输出,直到它在输入中找到\0终止符。 通过为输入和输出指定相同的数组,您将在读取输入时修改输入。

您必须检查编译器的strcat()的特定实现,但是如果您通过如下的简单实现进行跟踪,您应该看到为什么您的代码在一段时间后崩溃:

 char *strcat(char *dest, const char *src ) { char *ret = dest; if (dest && src) { while (*dest != 0) ++dest; while (*str != 0) *dest++ = *src++; *dest = 0; } return ret; } 

while (*dest != 0)循环之后, dest现在指向输入的\0终止符。 while (*str != 0)循环的第一次迭代然后用a替换该终结符,从而导致循环不再停在它应该的位置。 最终,循环将超过输入的边界并开始读取周围的内存,如果在命中无效内存之前没有找到另一个\0字节,它最终会崩溃。

根据strcat(3)

strcat()函数将src字符串附加到dest字符串,覆盖dest末尾的终止空字节(’\ 0’),然后添加一个终止空字节。 字符串可能不重叠 ,dest字符串必须有足够的空间用于结果。

原因是strcat在这个例子中做的第一件事是覆盖char * r的终止null。 然后它将循环遍历r,寻找它已被覆盖的null,最终徘徊到不安全的内存中(具体取决于堆栈的方向)

解决方案类似于strncat(r,r,strlen(r)),它将在覆盖null之前捕获R的长度。

迟到的答案。 只是想添加一些“图形”解释。

如果您考虑如何实现strcat ,它会在源字符串的第一个字符处初始化一个指针,并逐个字符地遍历源字符,直到它到达其空字节。 但由于源和目标字符串相同,可能会发生以下情况。

记忆开始像这样:

 abcdef \0 

source(s)和dest(d)指针都指向a on函数入口。 dest指针移动到最后,我们准备复制

 sdabcdef \0 sd abcdefa sd abcdefab sd abcdefabc sd abcdefabcd sd abcdefabcde sd abcdefabcdef sd abcdefabcdefa 

你可以看到源指针不会到达它的终止空字节,因为它在开始时被打乱了。 最终我们会在这里耗尽空间。

因此,由于这是一种可能的情况, strcat的定义不允许两个字符串重叠。 这种方式实现可以自由使用基本实现。