何时使用strncpy或memmove?

时间:2010-05-21 19:14:20

标签: c string

(gcc 4.4.4 c89)

我一直使用strncpy来复制字符串。我从未真正使用memmovememcpy。但是,我只是想知道您何时决定是使用strncpymemmove还是memcpy

我写的代码是针对客户端/服务器应用程序的。在文档中,他们使用bcopy。但是,我可以和其他人一样吗?

bcopy((char*)server->h_addr,
      (char*)&serv_addr.sin_addr.s_addr,
      server->h_length);

非常感谢,

6 个答案:

答案 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);

还返回它将写入的字节数,因此您可以判断是否发生了截断。