在以下场景中使用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
是否安全?
答案 0 :(得分:1)
正如您在声明中指明的那样:
memcpy(&buf[20], &buf[10], 10);
索引10
到19
的数据与索引20
到29
的数据不重叠,因此即使使用memcpy()
也是安全的您关心索引10
到19
的数据。
请注意,如果数据重叠,即使您不关心正在复制的数据,也不能安全使用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]
开始。 memmove
和std::copy
确实提供了这样的保证,因此在这种情况下可以安全地使用它们。
memcpy(&buf[10], &buf[20], 10);
不会重叠,因为&buf[10] + 9 == &buf[19]
是复制的制作地址且小于&buf[20]
。