C语言:字符串指针上的字符串连接

C语言:字符串指针上的字符串连接,c,C,我有这个add_str函数的代码: void add_str(char *str1, char *str2, char **res) { int i; int j = 0; res[0] = malloc((strlen(str1) + strlen(str2) + 1) * sizeof(char)); if (res[0] == NULL) return; for (i = 0; str1[i]; i++) res[0][j++] = st

我有这个add_str函数的代码:

void    add_str(char *str1, char *str2, char **res)
{
  int   i;
  int   j = 0;

  res[0] = malloc((strlen(str1) + strlen(str2) + 1) * sizeof(char));
  if (res[0] == NULL)
    return;
  for (i = 0; str1[i]; i++)
    res[0][j++] = str1[i];
  for (i = 0; str2[i]; i++)
    res[0][j++] = str2[i];
  res[0][j] = '\0';
}
它接收两个字符串,
str1
str2
和一个指针,一个字符串
**res
,它不是malloc。我的函数在**res上添加
str1
str2


我的问题是:有没有一种方法可以避免每次我必须对其进行操作时都写入
res[0]

*res

res
是指向指针的指针,因此在使用它之前需要取消对它的引用。您是对的,
res[0]
在这种情况下不是正确的方法。改用
(*res)

为什么还要传递指针?您也可以将其更改为:

char *add_str(char *str1, char *str2)
{
    char *res = malloc((strlen(str1) + strlen(str2) + 1));
    if (res == NULL)
        return NULL;

    char *ret = res;

    while(*str1 != 0)
        *res++ = *str1++;

    while(*str2 != 0)
        *res++ = *str2++;

    *res = '\0';
    return ret;
}

它具有相同的效果,您不必处理这种丑陋的构造。

这不是对您的问题的直接回答,而是更一般的编码建议:

为了正确管理程序中的所有动态内存操作,您应该努力(尽可能多地尝试)从同一个函数执行
x=malloc(…)
free(x)

在大多数情况下,如果您正确地设计了代码,那么您就可以实现这一点

在某些情况下,当流是异步的时,不可能这样做。例如,一个函数分配缓冲区,在系统中发生某个事件后,另一个函数(也称为回调)释放缓冲区

在这种情况下,您仍然应该尝试将这两个操作放在同一个“范围”(类、文件或模块)内


在您的编码示例中,函数
add_str
分配缓冲区,但不释放缓冲区,这意味着其他函数最终将不得不这样做(否则将导致内存泄漏)。因此,如果可能的话,您应该尝试在此函数之外执行
malloc

我将使用另一个指针变量来保存结果字符串,这样可以避免一直取消对结果变量的引用。当然,除此之外,您还应该避免使用数组下标运算符,因为您要做的是简单的指针解引用。我还对示例代码做了一些其他更改,使其更加简洁,可以忽略它们

void add_str(char *str1, char *str2, char **res) {
    char* result = *res = malloc((strlen(str1) + strlen(str2) + 1) * sizeof(char));
    //Dereferencing a NULL pointer will safely crash your program on any sane system.
    //if (!result) return;
    int   j = 0;    //Since C99 you are allowed to mix code and variable declarations.
    for(int i = 0; str1[i]; i++) result[j++] = str1[i];
    for(int i = 0; str2[i]; i++) result[j++] = str2[i];
    result[j] = '\0';
}
如果指针被充分利用,您的代码可以如下所示:

void add_str(char *str1, char *str2, char **res) {
    char* result = *res = malloc((strlen(str1) + strlen(str2) + 1) * sizeof(char));
    while(*str1) *result++ = *str1++;
    while(*str2) *result++ = *str2++;
    *result = '\0';
}

char*temp=res[0]?此外,您确实知道并使用strcpy和strcatOr您也可以只传递“char*res”而不是“char**res”。。。此外,您可以使用strcpy和strcat而不是两个for循环。如果OP想要继续使用当前代码,则需要使用括号,因为
*res[j]
(*res)[j]有所不同
@barakmanos,则OP无法在函数中分配内存。@JoachimPileborg:括号的说法是正确的。我会修正我的答案。谢谢@约阿希姆皮勒堡:我被纠正了。所以它可能是'res[0]'或'*res',但我看不出有任何明显的理由喜欢其中一个而不是另一个。这是胡说八道。
add_str
函数的全部要点是分配一个足够大的新字符串来容纳另外两个字符串。所需内存的计算被整齐地包装在所需的函数中,并隐藏在客户机代码中。您的建议将导致客户机代码与此类计算混淆。当然,必须让用户清楚,她需要稍后释放内存。另外,如果函数返回一个指针,而不是通过指针指向指针来更改指针,那么该函数将更易于使用。@M Oehm:首先,它不需要“更改指针指向指针”,因为它将从用户处接收一个“正常”指针,并简单地用数据填充指向的缓冲区。其次,这正是像
strcpy
memcpy
等函数的工作原理-它们不在内部分配新的缓冲区,但是,相反,他们从用户那里收到一个缓冲区,他们认为缓冲区足够大,可以安全地执行“复制”操作。有些人在试图解决当前问题时,通常只看眼前的问题,而忽略解决方案可能会出现的其他问题。在上述情况下,代码显然有效。但是在更大的范围内,您将拥有一个在代码中分散着“malloc”和“free”的系统。根据我的经验,您很快就会“失去”对动态内存管理的控制,最终会出现一些您甚至没有意识到的不同内存泄漏。是的,好的(?)旧字符串操作就是这样工作的。是的,不必要的马洛斯临时演员不是好的风格,即使你释放他们。是的,用C语言管理内存是很困难的。是的,OP的功能设计很古怪。尽管如此,这里讨论的标准函数将是可能溢出的
strcat
,或者
strncat
,其障碍是
n+1
字符写入溢出,其行为与
snprintf
的行为不一致。在我看来,OP似乎看到他需要频繁地计算长度和分配,并为此编写了一个函数。我看不出有什么不对。@M Ohem:这就是为什么我在回答的开头说‘这不是对你问题的直接回答,而是一个一般性的编码建议’。如果你同意我关于“好的旧字符串操作”(比如strcpy)的观点,那么我猜你也同意这个编码建议。OP可能有一个特殊的原因来实施他的方式。。。或者他可能不会。。。我给出了这个建议,以防万一后者是真的……这个原型是强加的,这是一个我想优化的学校练习。啊,我想这可能是真的。