Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 我的字符指针返回奇怪的字符串_C_Arrays_String_Char - Fatal编程技术网

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

C 我的字符指针返回奇怪的字符串,c,arrays,string,char,C,Arrays,String,Char,在尝试连接两个字符串char数组时,下面的代码通过return返回正确的结果,而不是通过引用传递的参数(即StrAdd函数中的char*dst)返回预期结果 关于后续结果;printf为st打印正确的连接字符串。但是变量s1也应该包含连接字符串。然而,s1打印出一些奇怪的东西 有人能找出它的毛病吗 #include <stdio.h> #include <stdlib.h> #include <string.h> char *StrAdd (char *ds

在尝试连接两个字符串char数组时,下面的代码通过return返回正确的结果,而不是通过引用传递的参数(即StrAdd函数中的char*dst)返回预期结果

关于后续结果;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);
}

您将s1传递给函数,然后对其调用free。执行此操作后,指针不再有效,您无法使用它。如果您这样做,就像在printf中那样,您会得到未定义的行为。

如果您想创建并返回一个新字符串,只需返回您分配的sTmp,而不释放dst

另一方面,如果确实希望更新传入的目标指针,则需要通过引用传递它,指向指针的指针:

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

好的,我在函数中释放dst一次,然后为该变量分配另一个内存空间。第二次分配不是通过标头中的*dst参数返回指针吗?正如在main中打印的那样,它通过return dst返回正确的指针;为什么不通过标题中的*dst?@merkez3110不,您正在释放s1并将新分配的内存分配给st。请参阅的正确实现。请原谅使用了错误的术语。我所说的标题并不是指头文件;我是指函数顶部的char*StrAdd char*dst,const char*src部分。@merkez3110,仅供参考,称为函数definition@merkez3110是的,你仍然需要空间,它只是取代了memcpy。我在第二个例子中使用了strcat示例。也许@2501的解释是正确的,但您的解决方案似乎更好。这样,我想,指向*s1的指针就不会丢失。我添加了一种更新s1的方法。只要确保在释放该字符串时没有其他对该字符串的引用。也就是说,它可能会被realloc释放。realloc可能不会更改指针。不过,您的第一个代码返回新定义的char*,即sTmp似乎更好。这样,如果我想在函数之后使用旧的s1,我会使用sNew=StrAdd s1,s2;如果我允许改变旧的s1,我将使用s1=跨距s1,s2;这方面的问题:s1=跨s1,s2;没有任何东西可以释放旧的s1,并且会导致内存泄漏。char*newS1=strads1,s2;自由1;s1=新闻1;就是这样做的。
printf ("Addresses after: %p %p\n", (void*)s1, (void*)st);