【问题标题】:Why does using strcat on character pointers crash? [duplicate]为什么在字符指针上使用 strcat 会崩溃? [复制]
【发布时间】:2011-01-27 02:18:50
【问题描述】:

为什么这段代码会崩溃? 在字符指针上使用strcat 非法?

#include <stdio.h>
#include <string.h>

int main()
{
   char *s1 = "Hello, ";
   char *s2 = "world!";
   char *s3 = strcat(s1, s2);
   printf("%s",s3);
   return 0;
}

请给出引用数组和指针的正确方法。

【问题讨论】:

  • 您使用 strcat 错误。它将第二个字符串附加到第一个字符串的末尾。它返回的字符串只是一种方便。您无法更改常量字符串(您的 s1),这就是它崩溃的原因。 s1 指向只读内存。
  • 如果一切正常,代码就不会崩溃。
  • 感谢杰森,只要我从你们这些优秀的人那里获得知识,我就不会为投票而烦恼。从现在开始,我将听从您的建议。再次感谢你真的很友善。
  • 我认为他是指将代码放入代码块中。在向问题或答案添加代码时,您可以突出显示所有代码文本,然后按文本框上方的“101 010”按钮以很好地格式化它。
  • 您应该将字符串文字声明为 const char*,然后编译器会为您捕获此类问题。

标签: c crash


【解决方案1】:

问题是s1 指向一个字符串文字,而您正试图通过将s2 附加到它来修改它。不允许修改字符串文字。您需要创建一个字符数组并将两个字符串都复制到其中,如下所示:

char *s1 = "Hello, ";
char *s2 = "world!";

char s3[100] = ""; /* note that it must be large enough! */
strcat(s3, s1);
strcat(s3, s2);
printf("%s", s3);

“足够大”是指至少strlen(s1) + strlen(s2) + 1+ 1 用于说明空终止符。

话虽如此,您应该认真考虑使用strncat(或者可以说更好但非标准的strlcat,如果可用的话),它们是经过边界检查的,因此远远优于strcat

【讨论】:

  • 可变长度数组 (c99) 或任何小于 100 的数组! :P
  • strcat 返回其第一个参数的原因是为了方便这种情况 - 这意味着您可以在一行中进行连接:strcat(strcat(s3, s1), s2);
  • 在几乎所有这样的情况下,我实际上更喜欢 snprintf 而不是 strncat。它对性能的影响很小,但更可能被正确使用,因为 strncat 的正确用法与库的其余部分不一致。 (“n”的意思与人们想象的不同。)
  • @rogue:我选择了明显足够大的东西,然后解释了“足够大”的真正含义。没错,在这种情况下,不需要 100 个字符。 @caf:很高兴知道;我不确定strcat 返回了什么(这就是我在C++ 领域生活太久的结果;-))。 @Dan:同意strncat 令人困惑和困难(因此提到了strlcat)。实际上,snprintf 对于长字符串或大量字符串可能更快,因为它不必遍历目标字符串来找到每个要连接的字符串的终止符。
  • 指向字符串字面量的指针通常应该声明为 const,这会将运行时崩溃变成编译时警告,从而更容易找到问题。
【解决方案2】:

在这种情况下,正确的方法是在目标字符串 (s1) 中分配足够的空间来存储 6 个额外的字符 (s2) 以及字符串的空终止符。

char s1[14] = "Hello, ";
char *s2 = "world!";
char *s3 = strcat(s1, s2);
printf("%s",s3);

【讨论】:

    【解决方案3】:

    这里引用 strcat() 手册中的一段话:“strcat() 函数将 src 字符串附加到 dest 字符串,覆盖 dest 末尾的空字节 ('\0'),然后添加一个终止符空字节。字符串不能重叠,并且目标字符串必须有足够的空间用于结果。"

    这里的问题是 s1 和 s2 指向的是“只读”的静态字符串,所以如果你尝试做一个 strcat 操作,在 dest 参数中有这样一个字符串,你会得到一个错误。

    在此处创建 hello world 字符串的最佳方法是对其进行 malloc,以便它能够同时包含 s1 和 s2。另外,不要忘记在 printf 格式字符串的末尾添加一个 '\n',否则您可能会感到惊讶。

    如果我是你,这是我会写的代码:

    
    int main()
    {
      char* s1 = "Hello ";
      char* s2 = "World !";
      char *s3 = malloc((strlen(s1) + strlen(s2) + 1) * sizeof(char));
    /* +1 is for the null terminating character
    and sizeof(*s3) is the actual size of a char. */
    
      if (s3)
      {
        strcat(s3, s1);
        strcat(s3, s2);
        printf("%s\n", s3);
        free(s3); // always free what you alloc when you don't need it anymore.
      }
      return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多