何时使用strncpy或memmove?

(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); 

非常感谢,

没有人回答你的所有问题。

strncpy()用于将数据从源复制到设置大小的dest,如果在缓冲区结束之前在源数组(字符串)中找到0x00字节,则复制(填充) 0x00 s。 与strcpy相反, strcpy将永远幸福地复制,直到找到0字节 – 即使所述字节远远超出了缓冲区。

无论源数据包含什么, memcpy()用于从源复制到dest。 它也往往是非常硬件优化的,并且通常一次读取系统字( int s / long s)以在对齐允许时加速复制。

memmove()用于从重叠的源和目标区域进行复制(比如将数组的内容移动到自身内部或类似的东西 – 因此移动助记符)。 它从后面而不是前面复制数据,以防止重叠区域中的数据丢失,然后才能读取数据。 它往往效率稍低,因为通常没有太多硬件帮助从后向前复制数据。

bcopy()及其亲属( bzero和其他一些人)是我现在看到的嵌入式bcopy()的字节复制函数。 通常,它会一次一个字节地从源到目标复制数据,以防止错位的内存地址问题,尽管任何好的memcpy都会处理这个,所以它的使用经常被怀疑。

祝好运!

你永远不应该使用strncpy (除非你正在处理它引入的罕见的特定情况)。 该函数不适用于零终止C字符串。 赋予该function的名称只是一个历史错误,恰好是试图使用它的人混淆的主要原因。 strncpy是一个引入的函数,用于支持所谓的“固定宽度”字符串,而不是零终止字符串。 使用带有零终止字符串的strncpy是一种糟糕的编程习惯,即使你可以将它鞭打成某种类似的“工作”用于此目的。

C库中不存在用于有限长度“安全”字符串复制的函数,但是某些实现以名称strlcpy提供它,该函数已经成为该函数的事实上的标准名称。 如果您的实现不提供strlcpy ,请自行实现。

此外,在许多情况下,您可以使用mem...函数替换str... mem...函数,即,当您知道要复制的确切字符数时。

strcpy (和其他str *方法)在遇到NULL(0)字节时停止。 memcpy和相关函数在遇到NULL字节时不会停止。

如果您有二进制数据,则必须使用memcpy。 在您的示例中,您正在复制二进制数据,而不是字符串数据。

strncpy是一种特殊情况,它将停止以NULL字节复制,但仍然继续用NULL填充输出,直到达到指定的长度。

如果你不需要strncpy的缓冲区填充行为但是想要不溢出缓冲区的安全性,请考虑strlcpy

来自维基百科 :

strlcpy提供了两个旨在帮助软件开发人员避免问题的function。 该函数将目标的大小作为参数,如果size参数正确,则避免缓冲区溢出。 如果此大小大于零,则始终将nul字节写入目标,因此生成的字符串始终以nul结尾(即使源字符串被截断以适合)。

仅当您知道字符串有足够的空间时才使用strncpy() – 因为它不保证空终止,并且如果目标比源字符串短(因为它将字符串填充到全长),则过于热情。 如果你知道长度,你可以使用memmove()

如果你知道字符串的长度, memmove()是一个明智的选择 – 并且名义上比strncpy()更快,因为它不必检查空值; 它只是复制相关的字节数。 (我假装memcpy()不存在,因为如果内存的源和目标区域重叠,它可能会失败,而memmove()无论如何都会正确。)

可以将bcopy()看作mem*()函数的古老变体。

如果您正在寻找安全/快速的复制方式,我对以下技术感到满意:

 memcpy( dest, src, sizeof (dest)); dest[sizeof(dest) - 1] = '\0'; // ensure null termination 

效率较低,但也可以限制写入的字节和null终止字符串:

 sprintf( dest, sizeof (dest), "%s", src); 

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