【问题标题】:Correct way to malloc space for a string and then insert characters into that space?为字符串分配空间然后将字符插入该空间的正确方法?
【发布时间】:2011-08-02 15:11:44
【问题描述】:

我有两个字符串,str1 和 str2。我希望将它们串联在堆中的空间上。我为他们分配空间:

char *concat = (char*) malloc(strlen(str1) + strlen(str2) + 1);

我可以这样做吗:

strcat(concat, str1);
strcat(concat, str2);

并且 concat 会给我在堆上连接两个字符串的位置吗?我问是因为似乎 strcat 实际上会将 str1 添加到使用 malloc 分配的空间的末尾。它是否正确?那么,str1 将出现在位置 strlen(str1) + strlen(str2) + 1。

我问的原因是我正在使用上面的方法,但是我在 valgrind 中遇到错误: 条件跳转或移动取决于未初始化的值

【问题讨论】:

    标签: c


    【解决方案1】:

    strcat(dest, src) 实际上所做的是搜索从dest 开始的空字节并继续前进,然后在那里写入src 字符串。

    malloc 之后,内存的内容是未定义的,所以你当前的代码可以做很多事情,其中​​大部分是不正确的。如果您在strcat 之前执行concat[0] = 0,那么您的代码可以工作,但必须搜索str1 的长度三次——一次搜索strlen,再次搜索第一个strcat,最后搜索一次第二个strcat

    不过,我建议使用memcpy:

    size_t len1 = strlen(str1), len2 = strlen(str2);
    char *concat = (char*) malloc(len1 + len2 + 1);
    
    memcpy(concat, str1, len1);
    memcpy(concat+len1, str2, len2+1);
    

    这利用了这样一个事实,即您从一开始就知道要两个字符串的字节到哪里,以及有多少。

    【讨论】:

    • +1 绝对是一个非常好的方法。我可能会使用memmove() 而不是memcpy(),因为虽然memcpy() 在这种情况下是安全的,但它并不总是安全的,但memmove() 总是安全的。
    • 不要在这里使用memmove;这令人困惑。 memmove 的任何用法都应该用来证明您正在做一些非常不同和不寻常的事情。如果我在这里看到memmove,我会花一两分钟的时间来弄清楚为什么有人使用它的#*$@ 以及是否发生了什么可疑的事情......
    【解决方案2】:

    你想先做一个 strcpy 然后再做一个 strcat:

    strcpy(concat, str1);
    strcat(concat, str2);
    

    strcat 依靠空终止符 ('\0') 来知道从哪里开始。如果你只是 malloc 和 strcat,它会做一些讨厌的事情。

    不,strcpy 和 strcat 都不会进行任何类型的隐式分配或重新分配。

    【讨论】:

      【解决方案3】:

      我个人会做以下事情:

      size_t length = strlen(str1) + strlen(str2) + 1;
      char *concat = malloc(sizeof(char) * length);
      
      if(concat == NULL)
      {
          // error
      }
      
      snprintf(concat, length, "%s%s", str1, str2);
      

      【讨论】:

      • +1 用于提及错误检查。 snprintf() 通常是一个很好的解决方案,尽管在这里它有点矫枉过正。
      • 不要使用strlen 来计算长度。使用length=snprintf(0,0,"%s%s",str1,str2); 或只使用asprintf(并确保包含您自己的版本 - 它是snprintf 的简单包装器 - 对于不包含此 GNU 扩展的系统)。
      • R 在上面的评论由他自己在这里解释(必须阅读以理解建议):stackoverflow.com/a/5615561/340236
      猜你喜欢
      • 2018-04-07
      • 2010-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-27
      • 2014-12-23
      相关资源
      最近更新 更多