何时使用strncpy或memmove?

ant*_*009 17 c string

(gcc 4.4.4 c89)

我一直习惯于strncpy复制字符串.我从来没有真正使用memmovememcpy非常.然而,当你决定是否要使用我只是想知道strncpy,memmovememcpy

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

bcopy((char*)server->h_addr,
      (char*)&serv_addr.sin_addr.s_addr,
      server->h_length);
Run Code Online (Sandbox Code Playgroud)

非常感谢,

Mic*_*gan 22

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

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

memmove()用于从重叠的源和目标区域进行复制(比如将数组的内容移动到自身内部或类似的东西 - 因此移动助记符).它使用策略(例如可能从后面而不是从前面复制数据)来防止由重叠区域引起的问题.由于通常没有太多硬件帮助从后向前复制数据,因此效率可能稍低.

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

祝好运!

  • strncpy不会提前终止副本.strncpy准确写入给定的字节数,或者只是复制字符串的开头(如果它太长),或者在复制的末尾添加零来填充缓冲区. (4认同)
  • @MichaelDorgan我偶然发现了这个.`memmove()`在你的答案中是不正确的.如果源地址大于目标地址,则必须从前面开始.如果源地址较小,则必须从后面开始. (2认同)

AnT*_*AnT 12

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

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

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

  • @frunsi:绝对确定。`strncpy` 的历史是众所周知且有据可查的。这里没有任何“恕我直言”的空间。创建该函数是为了填充一种古老版本的 Unix 文件系统中的 14 个字符的长文件名字段。这是它唯一被有意义地使用过的角色,也是它唯一适合的角色。 (2认同)
  • @robUK:对不起,但这简直是胡说八道.地球上当前dst字符串的长度与我想要复制的字符数有什么关系?实际上,在100个中的99个案例中,dst缓冲区将是未初始化的,因此对它应用`strlen`就没有任何意义. (2认同)
  • @robUK:"没有缓冲区溢出"是不够的.除了"没有缓冲区溢出"之外,我们还希望获得正确的结果(dst中的以零结尾的字符串),并且我们还希望避免浪费时间做不必要的工作.在一般情况下,`strncpy`对我们没有帮助.这就是为什么我们不为此目的使用`strncpy`. (2认同)

Yan*_*min 6

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

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

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

  • 但是,strncpy不会停止填充目标缓冲区.strncpy准确写入给定的字节数,或者只是复制字符串的开头(如果它太长),或者在复制的末尾添加零来填充缓冲区. (2认同)

Dou*_*rie 5

如果您不需要缓冲区填充行为,strncpy但希望安全性不会溢出缓冲区,请考虑strlcpy

来自维基百科:

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