C 结构中的字符串。腐化

C 结构中的字符串。腐化,c,struct,C,Struct,有这样的结构 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-&

有这样的结构

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);
有什么想法吗?

我认为
strncpy()
函数不是您想要的。考虑调用:

strncpy(addr->name, name, MAX_DATA);
如果
name
包含
MAX\u DATA
或更多字符,这将把
name
中的字节复制到
addr->name
中,并且不会NUL终止目标。您有两个常规选择:

  • 使用以下代码手动NUL终止结果:

    addr->name[MAX_DATA-1] = '\0';
    
    但是,这很容易出错,因为您必须记住每次都要这样做

  • 使用库函数,例如
    strlcpy()
    (通常在BSD派生的系统上可用,但不是标准的),该函数总是NUL终止目标,即使源代码不完全适合


  • strncpy
    返回其在so之后的第一个参数

    char *res = strncpy(addr->name, name, MAX_DATA);
    
    变量
    res
    保存
    addr->name
    (相当于
    &(addr->name[0])
    ),因此当

    它相当于

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

    此赋值会损坏
    addr->name
    的第一个字符。正如Greg Hewgill所说,如果(!res)死亡(“名称复制失败”),则不需要检查甚至保存strncpy的返回值。。。我闻到PHP:D
    voiddie(constchar*message){if(errno){perror(message);}else{printf(“ERROR:%s\n”,message);}exit(1);}
    来自PHP:)不需要检查
    strncpy()的返回值,因为它总是返回其第一个参数的值。始终。还要注意,如果
    source
    name
    )是
    MAX\u DATA
    字符长度
    strncpy
    ,则不会在
    dest
    (addr->name)末尾为您添加空字符。99.99%的时间strncpy是错误的函数。之所以使用C,是因为Ken Thompson希望它用于编写UNIX目录项,这些目录项是14字节的NUL填充字段,但不是以NUL结尾的字段。请注意,strlcpy不是任何标准的一部分,可能无法在所有平台(包括Linux glibc)上使用。注意:如果需要确保字符串以null结尾,strncpy的第三个参数应该是MAX_DATA-1,您应该手动将最后一个字符设置为0。只有当第二个参数小于第一个参数的大小时,strncopy才会插入null。更简单的解决方案是将MAX_DATA常量增加1,然后将MAX_DATA-1作为第三个参数传递,从而为空终止保留空间。同样,这假定您将调用依赖于空终止的函数。
    addr->name[0] = strncpy(addr->email, email, MAX_DATA);