memcpy有奇怪的结果

时间:2013-06-21 00:59:42

标签: c token memcpy

我从一个程序向另一个程序发送一个格式如此的字符串:number lastname firstname middlei ID GPA

接收程序看到正确的字符串,并将此字符串存储到缓冲区中。该字符串被标记化并且在switch语句中使用该数字。相应案例的代码如下所示。

tok = strtok( arg, " " );
printf( "the first token is %s\n", tok );
memcpy( ptr->student.lname, tok, 10 );
tok = strtok( NULL, " " );
memcpy( ptr->student.fname, tok, 10 );
tok = strtok( NULL, " " );
ptr->student.initial = *tok;
tok = strtok( NULL, " " );
sscanf( tok, "%lu", &ptr->student.SID );
tok = strtok( NULL, " " );
sscanf( tok, "%f", &ptr->student.GPA );
// few more pointer and location initializations...
printf( "lu %s %s %c %f\n", ptr->student.SID, ptr->student.lname,
    ptr->student.fname, ptr->student.initial, ptr->student.GPA );

输入字符串为:5 lastnamereallylong,firstnamereallylong,X,1234,4.0

第一个程序缩短为:5 lastnamere firstnamer X 1234 4.0

第二个程序的输出如下:

the first tok is lastnamere
1234 lastnamereXfirstnamer firstnamer X 4.000000

有人可以帮我弄清楚这里发生了什么吗?我可以理解没有正确使用memcopy,但我认为这不会改变原始信息的顺序。

1 个答案:

答案 0 :(得分:2)

这里发生的是未定义的行为:你告诉memcpy复制令牌的前10个字符,但是当令牌长度超过10个字符时,就意味着字符串不会出现为空终止。将此类字符串传递给printf("%s", ...)是未定义的行为。

要解决此问题,您应该通过设置ptr->student.lname[9] = '\0'来强制终止,如果您想使用固定长度的字符串,或者使用strdup来允许可变长度的字符串。

最后,使用strtok有一种线程安全的替代方法 - 您可以使用strtok_r