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终止目标。您有两个常规选择:
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:Dvoiddie(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);