【问题标题】:Why do I first have to strcpy() before strcat()?为什么我必须先 strcpy() 在 strcat() 之前?
【发布时间】:2013-09-21 05:56:06
【问题描述】:

为什么这段代码会产生运行时问题:

char stuff[100];
strcat(stuff,"hi ");
strcat(stuff,"there");

但这不是吗?

char stuff[100];
strcpy(stuff,"hi ");
strcat(stuff,"there");

【问题讨论】:

    标签: c c-strings


    【解决方案1】:

    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.
    

    【讨论】:

    • {} 不是 C 中的有效初始化程序。
    • 呸!我错过了C 标签。谢谢。
    • 不过你应该可以char stuff[100] = {0};
    • 我更喜欢char stuff[100]=""; 进行初始化,尽管大多数情况下第一个赋值一个strcpy。
    【解决方案2】:

    在第一种情况下,stuff 包含垃圾。 strcat 要求目标和源都包含正确的以 null 结尾的字符串。

    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 个字节(提高清晰度可能值得任何小的性能问题)。

    【讨论】:

      【解决方案3】:

      因为stuff 在调用strcpy 之前未初始化。声明后stuff 不是空字符串,它是未初始化的数据。

      strcat 将数据附加到字符串的末尾 - 即它在字符串中找到空终止符并在其后添加字符。未初始化的字符串不保证有空终止符,因此strcat 可能会崩溃。

      如果要初始化stuff,如下所示,您可以执行 strcat:

      char stuff[100] = "";
      strcat(stuff,"hi ");
      strcat(stuff,"there");
      

      【讨论】:

      • 答案是完整的,但在初学者不理解的情况下:第一行添加了空字符串的初始化(其中没有字符) - 但作为双引号中的任何字符串,它都有一个 null最后的终止字符(通常为 0x00)。这就是strcat 正在寻找的角色。换句话说,初始化是这样做的:stuff[0] = 0;
      【解决方案4】:

      另外,我建议不要使用strcpystrcat,因为它们会导致一些意想不到的问题。

      使用strncpystrncat,因为它们有助于防止缓冲区溢出。

      【解决方案5】:

      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;
         }
      

      正如您在此实现中所见,strlen(dest) 不会返回正确的字符串长度,除非 dest 被初始化为正确的 c 字符串值。您可能很幸运在 char stuff[100]; 有一个第一个值为零的数组,但您不应该依赖它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-22
        • 1970-01-01
        • 2020-09-03
        相关资源
        最近更新 更多