我有二进制文件读取缓冲区,它读取可变长度的结构。在缓冲区末尾附近总会有不完整的结构。我想将这样的缓冲区尾移到它的开头,然后在下一个文件读取期间读取buffer_size - tail_len
个字节。像这样:
char[8192] buf;
cur = 0, rcur = 0;
while(1){
read("file", &buf[rcur], 8192-rcur);
while (cur + sizeof(mystruct) < 8192){
mystruct_ptr = &buf[cur];
if (mystruct_prt->tailsize + cur >= 8192) break; //incomplete
//do stuff
cur += sizeof(mystruct) + mystruct_ptr->tailsize;
}
memcpy(buf,&buf[cur],8192-cur);
rcur=8192-cur;
cur = 0;
}
如果尾部很小且缓冲区很大,它应该可以正常,因为memcpy
很可能在单次复制迭代期间不会与复制的内存段重叠。然而,当尾巴变大时,它听起来有点冒险 - 大于50%的缓冲区。
如果缓冲区非常庞大且尾部也很大,那么它仍然应该没问题,因为在单个操作中可以复制多少数据的物理限制,如果我没记错的话,对于使用向量单元的现代x86_64 CPU来说,这是512字节。我考虑添加检查尾部长度的条件,如果它与缓冲区的大小相比太大,执行天真的逐字节复制,但问题是:
memcpy
?
答案 0 :(得分:2)
根据标准,如果源和目标区域重叠,memcpy()
具有未定义的行为。区域有多大或者有多少重叠并不重要。未定义的行为不能被认为是安全的。
如果您正在编写特定的实现,并且该实现定义了某些此类复制的行为,并且您不关心可移植性,那么您可以依赖于您的实现在这方面的特定行为。但我建议不要。这将是一个令人讨厌的错误等待咬人决定使用代码与其他一些实现。甚至可能是未来你。
在这种特殊情况下,使用专用于此目的的memmove()
替代方案,会使memcpy()
赌博完全鲁莽。