C复制到常量字符*

时间:2015-07-26 14:52:01

标签: c struct strncpy

我有一个项目,我收到了一个包含以下内容的头文件:

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

朋友是另一个不在我的问题范围内的结构

在我需要创建的源文件中,我创建了一个struct和后续的全局变量:

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

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

1 个答案:

答案 0 :(得分:2)

这将导致一个问题:

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

您似乎不知道 null终止。想象一下,你后来想要读出users->user->name。你怎么知道名字何时结束?您没有将信息strlen(name)保存在任何地方。

出于这个原因,C中的字符串在它们的末尾有一个标记。该标记是空字节(值0的字节)。然后,字符串处理函数知道字符串结尾的位置(通常是已分配内存的结尾)。

所以你需要分配一个额外的字节,并使用正确的复制功能:

users->user->name = malloc(strlen(name) + 1);
strcpy(users->user->name, name);

根据经验,从不使用strncpy strcpysnprintf函数更合适。 strncpy是以前几天的遗物。

你有类似的(但更糟糕的是,因为你在程序中稍后使用sizeof而没有真正了解sizeof做什么)。希望你在阅读我的答案后现在也可以解决这个问题。

  

我需要将const char *复制到const char *,

您需要停止将指针视为“包含”任何内容。指针指向记忆的其他部分,它们本身必须存在。

您需要将一些字节从一个地方复制到另一个地方,在那里您可以指向这两个地点。

现在,您无法通过const char *写入某个位置。这就是const的用途。但是,只读内存中的位置:您只需要对它进行malloc。所以这个位置肯定是安全的。您只需要重新排列代码,以便将非const指针传递给写入函数。一种方法是:

char *new_name = malloc(strlen(name) + 1);
strcpy(new_name, name);
users->user->name = new_name;

另一种方式,如果你在POSIX系统上,那将是:

users->user->name = strdup(name);

具有相同的效果。