在重叠区域安全使用memcpy

时间:2014-01-18 13:42:55

标签: c memcpy memmove

在以下场景中使用memcpy是否安全,其中一个是将数据从较大索引复制到同一块中的较小索引。例如:

char buf[100];
// fill in the data ...
memcpy(&buf[10], &buf[15], 10);

在上面的场景中,我不关心位置10 - 19的数据,如果被覆盖则很好。有没有理由为什么要避免这种情况而使用memmove呢?

编辑:对不起我没有正确地传达我的意图,所以我说我有索引10 - 19的数据和索引15 - 24的数据,我想要复制数据从15 - 24超过10 - 19,我不喜欢关心10到19之间的数据,即使它们重叠,我们memcpy是否安全?

3 个答案:

答案 0 :(得分:1)

正如您在声明中指明的那样:

memcpy(&buf[20], &buf[10], 10);

索引1019的数据与索引2029的数据不重叠,因此即使使用memcpy()也是安全的您关心索引1019的数据。

请注意,如果数据重叠,即使您不关心正在复制的数据,也不能安全使用memcpy,因为未指定memcpy复制的方向

答案 1 :(得分:1)

修改

根据您的修改,反转以下答案,因为现在您不同意restrict约束。


旧答案

是的,这是安全的。您正在buf[10]通过buf[19]复制buf[20]buf[29]。 (请注意,memcpy的第一个参数是目标。因此,buf[10]buf[19] 被覆盖。)

memcpy在C11中定义为:

void *memcpy(void * restrict s1, const void * restrict s2, size_t n);

注意restrict关键字。 C11在6.7.3.8说(强调我的):

  

通过限制限定指针访问的对象具有特殊关联   用那个指针。此关联,在下面的6.7.3.1中定义,要求所有访问   该对象直接或间接使用该特定指针的值 .135)预期的   使用restrict限定符(如寄存器存储类)是为了促进   优化,并从所有预处理转换中删除限定符的所有实例   构成一致程序的单位不会改变其含义(即可观察到的)   行为)。

在您的示例中,buf[10]buf[19]只能通过s2指针访问,而buf[20]buf[29]只能通过{{1}访问指针。因此,您对s1的使用完全可以。

简单来说,只要您提供给memcpy的数组不重叠,就可以了。

答案 2 :(得分:0)

很安全。没有理由使用memmove.

memcpy没有指定方向,因此memcpy(&buf[20], &buf[10], 20);会让人感到困惑。我们必须确保副本从&buf[20]开始。 memmovestd::copy确实提供了这样的保证,因此在这种情况下可以安全地使用它们。

memcpy(&buf[10], &buf[20], 10);不会重叠,因为&buf[10] + 9 == &buf[19]是复制的制作地址且小于&buf[20]