我的char指针返回奇怪的字符串

时间:2014-10-12 15:12:53

标签: c arrays string char

当尝试连接两个字符串(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);
}

2 个答案:

答案 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);

在此之后,s1st指向相同的字符串,请尝试以查看:

printf ("Addresses after: %p %p\n", (void*)s1, (void*)st);