为什么我不能malloc请求内存并使用字符串在函数中赋值,但结构体中的字符串可以?

ffx8fchx  于 2022-12-03  发布在  其他
关注(0)|答案(3)|浏览(165)

为什么它是错的

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void func(char* dest, const char* src)
{
    dest = malloc(strlen(src) + 1);
    strcpy(dest, src);
}

int main()
{
    char* name0;
    char* name1 = "Jam";

    func(name0, name1);
    puts(name0);
    
    free(name0);
    return 0;
}

but

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct st
{
    char* name;
};

void func(struct st* st1, const struct st* st2);

int main(void)
{
    struct st name0, name1;
    name1.name = "Jam";

    func(&name0, &name1);

    puts(name0.name);

    free(name0.name);
    name0.name = NULL;

    exit(0);
}

void changename(struct st* st1, const struct st* st2)
{
    st1->name = malloc(strlen(st2->name) + 1);
    if(st1->name == NULL)
        exit(1);
    strcpy(st1->name, st2->name);
}

`是对的

我试着用第一种方法来解释为什么第二种方法有意义,为什么第二种方法能解决问题,但是第一种方法报告了一个错误,没有给予我想要的答案。#为什么我不能用字符串在函数中请求内存和赋值,而结构体中的字符串可以?

qnzebej0

qnzebej01#

尝试通过引用而不是通过值将指针传递给字符指针。

void func(char** dest, const char* src)
{
    *dest = malloc(strlen(src) + 1);
    strcpy(*dest, src);
}
mwecs4sa

mwecs4sa2#

撇开可能存在的其他错误不谈,这两者之间的最大区别是增加了一个间接层。
考虑以下结构

struct foo { 
     int * x;
};

而现在这两个功能:

void f1(int* a) {  a = nullptr; }

void f2(foo* f) { f.x. = nullptr;  f = nullptr;}

当调用f1时,修改本地副本a对调用方传递的指针没有影响:

int i = 0;
int* ptr = &i;
f1(ptr);                // a copy of ptr is made
assert( ptr == &i);     // ptr still points to i

对于传递给f2的指针也是如此。在f2中修改f对调用方传递的指针没有影响。但是,您可以在f2中修改f指向的内容,并且这对调用方是可见的。

foo fo;
int i = 0;
fo.x = &i;
foo* foptr = &fo;
f2(foptr);           // a copy of foptr is made, it also points to fo

assert( fo.x == nullptr);     // the function did modif fo
assert( foptr->x == nullptr); 

assert( foptr == &fo );       // same as above, foptr still points to fo
h79rfbju

h79rfbju3#

在一种情况下,你有func(name0, name1),在另一种情况下,你有func(&name0, &name1)
函数不能更改传递给它的值。当您传递name0时,函数不能更改name0。它只接收其值的副本。同样,当您传递&name0时,函数不能更改&name0的值。但是,该值指向一个对象。函数可以更改它指向的对象。
当您传递&name0,且函式执行st1->name =…时,它会变更st1所指向之对象内的name,也就是name0
如果调用第一个函数的方式与调用第二个函数func(&name0, &name1)的方式相同,那么函数将被传递指向name0name1的指针,而不是传递它们的值。然后,您需要更改func以匹配:

void func(char **dest, const char **src)
{
    *dest = malloc(strlen(*src) + 1);
    strcpy(*dest, *src);
}

通过这些更改,函数将对其参数destsrc所指向的内容进行操作,而不是对destsrc中的值进行操作。
(It不需要更改调用和函数定义中的src参数,因为不需要更改源对象(我更改它只是为了匹配第二个函数)。

相关问题