我有一个项目,我得到了一个头文件,其中包含:

typedef struct User_struct {
    const char *name;
    Friends amigos;
} User;

朋友是另一个不在我问题范围内的结构
在我需要创建的源文件中,我创建了一个结构和随后的全局变量:
typedef struct UserList{
        User *user;
        struct UserList *next;
}UserList;

static UserList *users;

有一个初始化函数create_amigonet,其中我将内存分配给users,另一个分配给users->user。我的问题是这个函数:
void addUser( const char *name )
{
        UserList *new_users;
        UserList *iter;

        if(users->user->name == NULL)
        {
                users->user->name = malloc(strlen(name));
                strncpy((users->user->name,name,strlen(name));
                return;
        }

        for(iter = users; iter != NULL; iter = iter->next)
        {
                if(iter->user->name == name)
                        return;
        }

        new_users = malloc(sizeof(UserList));
        if(new_users != NULL)
        {
                new_users->user = malloc(sizeof(User));
                new_users->user->name = malloc(sizeof(name)+1);
                strncpy(new_users->user->name,name,sizeof(name)+1);
                new_users->user->amigos = NULL;
                new_users->next = users;
                users = new_users;
        }
        return;
}

我需要将aconst char *复制到aconst char *中,并且不允许更改用户结构或函数的定义。我不确定如何复制/初始化结构中的任何节点。我可以更改UserList,这是我创建的一个“用户”链接列表结构。

最佳答案

这将导致一个问题:

users->user->name = malloc(strlen(name));
strncpy((users->user->name,name,strlen(name));

你好像不知道无效终止。想象一下,您稍后想从users->user->name中读出。你怎么知道名字什么时候结束?你没有把信息保存在任何地方。
因此,C中的字符串在其末尾有一个标记。该标记是一个空字节(字节值strlen(name))。然后,字符串处理函数知道字符串的结尾在哪里(通常是分配内存的结尾)。
因此,您需要分配一个额外的字节,并使用适当的复制函数:
users->user->name = malloc(strlen(name) + 1);
strcpy(users->user->name, name);

根据经验,不要使用0strncpystrcpy函数更合适。snprintf是过去的遗物。
在您的程序中有一个类似的(但更糟的是,因为您后来在使用strncpy时并没有真正理解sizeof的功能)。希望你现在也能解决这个问题,在阅读了我的答案之后。
我需要把常量字符*复制到常量字符*,
你需要停止认为指针“包含”了任何东西。指针指向内存的其他部分,它们本身就必须存在。
您需要将一些字节从一个位置复制到另一个位置,在这里您有指向两个位置的指针。
现在,您不能通过sizeof写入位置。这就是const char *的作用。但是,这个位置不在只读内存中:您只需将其malloc。所以这个位置绝对是安全的。您只需要重新排列代码,以便向写入函数传递一个非常量指针。一种方法是:
char *new_name = malloc(strlen(name) + 1);
strcpy(new_name, name);
users->user->name = new_name;

另一种方法是,如果您使用的是POSIX系统,那么:
users->user->name = strdup(name);

也有同样的效果。

09-20 10:29