当尝试连接两个字符串(char数组)时,下面的代码通过return
返回正确的结果,但不通过引用传递的参数(即char *dst
中的StrAdd
返回预期结果1}}功能)。
关于“后”结果; printf
为st打印正确的连接字符串。但变量“s1”应该包含连接的字符串。然而,s1打印出一些奇怪的东西。
有人可以弄清楚它有什么问题吗?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *StrAdd (char *dst, const char *src) {
/* add source string "src" at the end of destination string "dst"
i.e. concatenate
*/
size_t lenDst = strlen (dst);
size_t lenSrc = strlen (src);
size_t lenTot = lenDst + lenSrc + 1;
char *sTmp = (char *) malloc (lenTot);
memcpy (&sTmp [0], &dst [0], lenDst);
memcpy (&sTmp [lenDst], &src [0], lenSrc);
sTmp [lenTot - 1] = '\0';
free (dst);
dst = (char *) malloc (lenTot);
memcpy (&dst [0], &sTmp [0], lenTot);
free (sTmp);
return (dst);
}
int main () {
char *s1 = strdup ("Xxxxx");
char *s2 = strdup ("Yyyyy");
char *st = strdup ("Qqqqq");
printf ("s1 before: \"%s\"\n", s1);
printf ("s2 before: \"%s\"\n", s2);
printf ("st before: \"%s\"\n", st);
printf ("\n");
st = StrAdd (s1, s2);
printf ("s1 after : \"%s\"\n", s1); // weird???
printf ("s2 after : \"%s\"\n", s2); // ok
printf ("st after : \"%s\"\n", st); // ok
printf ("\n");
return (0);
}
答案 0 :(得分:8)
您将s1
传递给该函数,然后在其上调用free。执行此操作后,指针不再有效,您无法使用它。如果你这样做,就像你在printf()中所做的那样,你会得到未定义的行为。
答案 1 :(得分:4)
如果您想创建并返回新字符串,只需返回您分配的sTmp
,不要释放dst
。
char *StrAdd (const char *dst, const char *src) {
size_t lenDst = strlen (dst);
size_t lenSrc = strlen (src);
size_t lenTot = lenDst + lenSrc + 1;
char *sTmp = (char *) malloc (lenTot);
memcpy (&sTmp [0], &dst [0], lenDst);
memcpy (&sTmp [lenDst], &src [0], lenSrc + 1); //+1 copies the existing nil char from src
return sTmp;
}
另一方面,如果您希望更新传入的目标指针,则需要通过引用传递它,指向指针的指针:
char *StrAdd (char** dstPtr, const char *src) {
char* dst = *dstPtr;
size_t lenDst = strlen (dst);
size_t lenSrc = strlen (src);
size_t lenTot = lenDst + lenSrc + 1;
char *sTmp = (char *) realloc (dst, lenTot); //realloc will also copy the old data for us
strcat(sTmp, src); //same as the second memcpy
*dstPtr = sTmp; //update dest pointer
return sTmp;
}
但你需要这样称呼它:
st = StrAdd (&s1, s2);
在此之后,s1
和st
指向相同的字符串,请尝试以查看:
printf ("Addresses after: %p %p\n", (void*)s1, (void*)st);