(gcc 4.4.4 c89)
我一直使用strncpy
来复制字符串。我从未真正使用memmove
或memcpy
。但是,我只是想知道您何时决定是使用strncpy
,memmove
还是memcpy
?
我写的代码是针对客户端/服务器应用程序的。在文档中,他们使用bcopy
。但是,我可以和其他人一样吗?
bcopy((char*)server->h_addr,
(char*)&serv_addr.sin_addr.s_addr,
server->h_length);
非常感谢,
答案 0 :(得分:22)
strncpy()
用于将数据从源复制到设置大小的dest,如果在源数组中找到0x00
字节,则复制(填充)0x00
s )在缓冲区结束之前。与strcpy
相反,0
将永远幸福地复制,直到找到memcpy()
字节 - 即使所述字节远远超出了缓冲区。
int
用于从源复制到dest。它也往往是非常硬件优化的,并且通常一次读取系统字(long
s / memmove()
s)以在对齐允许时加速复制。
bcopy()
用于从重叠的源和目标区域进行复制(比如将数组的内容移动到其自身内部或类似的东西 - 因此移动助记符)。它使用策略(例如可能从后面而不是从前面复制数据)来防止由重叠区域引起的问题。由于通常没有太多硬件帮助从后向前复制数据,因此效率可能略低。
bzero
及其亲属(memcpy
和其他一些人)是我现在看到的嵌入式字体中的字节复制函数。通常,它会一次一个字节地从源到目标复制数据,以防止错位的内存地址问题,尽管任何好的{{1}}都会处理这个问题,所以它的使用经常被怀疑。
答案 1 :(得分:12)
你永远不应该使用strncpy
(除非你正在处理它所引入的罕见特定情况)。该函数不适用于零终止C字符串。赋予该功能的名称只是一个历史错误,恰好是试图使用它的人混淆的主要原因。 strncpy
是为支持所谓的“固定宽度”字符串而不是零终止字符串而引入的函数。使用带有零终止字符串的strncpy
是不好的编程习惯,即使你可以将它鞭打为某种类似的“工作”用于此目的。
C库中不存在有限长度“安全”字符串复制的函数,但是某些实现以名称strlcpy
提供它,该函数已成为此函数的事实上的标准名称。如果您的实施没有提供strlcpy
,请自行实施。
此外,在许多情况下,您可以使用str...
函数替换mem...
函数,即当您知道要复制的确切字符数时。
答案 2 :(得分:6)
strcpy
(以及其他str *方法)在遇到NULL(0)字节时停止。 memcpy
和相关函数在遇到NULL字节时不会停止。
如果您有二进制数据,则必须使用memcpy。在您的示例中,您正在复制二进制数据,而不是字符串数据。
strncpy
是一种特殊情况,它将以NULL字节停止复制,但仍然继续用NULL填充输出,直到指定的长度。
答案 3 :(得分:5)
如果您不需要strncpy
的缓冲区填充行为但希望安全性不会溢出缓冲区,请考虑strlcpy
来自wikipedia:
strlcpy
提供了两个旨在帮助软件开发人员避免问题的功能。该函数将目标的大小作为参数,如果size参数正确,则避免缓冲区溢出。如果此大小大于零,则始终将nul字节写入目标,因此生成的字符串始终以nul结尾(即使源字符串被截断以适合)。
答案 4 :(得分:4)
仅当您知道字符串有足够的空间时才使用strncpy()
- 因为它不保证空终止,并且如果目标比源字符串短,则过于热情(因为它填充了字符串到全长)。如果您知道长度,可以使用memmove()
...
如果你知道字符串的长度,memmove()
是一个明智的选择 - 名义上比strncpy()
快,因为它不需要检查空值;它只是复制相关的字节数。 (我假装memcpy()
不存在,因为如果内存的源和目标区域重叠,它可能会失败,而memmove()
无论如何都会正确。)
将bcopy()
视为mem*()
函数的古老变体。
答案 5 :(得分:2)
如果您正在寻找安全/快速的复制方式,我对以下技术感到满意:
memcpy( dest, src, sizeof (dest));
dest[sizeof(dest) - 1] = '\0'; // ensure null termination
效率较低,但也可以限制写入的字节数并将字符串空终止:
sprintf( dest, sizeof (dest), "%s", src);
还返回它将写入的字节数,因此您可以判断是否发生了截断。