2

有这样的结构。

struct Address {
    int id;
    int set;
    char name[MAX_DATA];
    char email[MAX_DATA];
};

以及设置地址的函数。

void Database_set(struct Connection *conn, int id, const char *name, const char *email) {
    struct Address *addr = &conn->db->rows[id];
    if(addr->set) die("Address already set");

    addr->set = 1;
    char *res = strncpy(addr->name, name, MAX_DATA);
    if(!res) die("Name copy failed");

    *res = strncpy(addr->email, email, MAX_DATA);
    if(!res) die("Email copy failed");
}

但是 addr->name 的第一个字符在此行之后被损坏。

*res = strncpy(addr->email, email, MAX_DATA);

有任何想法吗?

4

2 回答 2

6

strncpy返回它的第一个参数,所以之后

char *res = strncpy(addr->name, name, MAX_DATA);

变量res成立addr->name(等效地,&(addr->name[0]))所以当

*res = strncpy(addr->email, email, MAX_DATA);

运行它相当于

addr->name[0] = strncpy(addr->email, email, MAX_DATA);

这个赋值是破坏addr->name. 正如 Greg Hewgill 所说,您不需要检查甚至保存strncpy.

于 2012-06-23T22:34:15.100 回答
3

我认为该strncpy()功能不是您想要的。考虑调用:

strncpy(addr->name, name, MAX_DATA);

如果name具有MAX_DATA或更多字符,这会将字节复制name到目标中addr->name,并且不会以 NUL 终止目标。您有两种一般选择:

  1. 使用代码手动 NUL 终止结果,例如

    addr->name[MAX_DATA-1] = '\0';
    

    但是,这很容易出错,因为您必须记住每次都这样做。

  2. 使用一个库函数,例如strlcpy()(通常在 BSD 派生系统上可用,但不是标准的),它总是以 NUL 终止目标,即使源不完全适合。

于 2012-06-23T22:33:45.417 回答