如果我的代码中有这样的内容:
void f(struct foo *x, struct foo *y)
{
*x = *y; // structure copy (memcpy?)
}
如果x和y指向相同的地址,会发生什么?
这是有效的代码吗?如果编译器将赋值转换为具有可能无效的操作数的memcpy调用(它们不允许重叠)会怎样?
[是的,我知道在这种情况下我可以使用“restrict”,但我们发现的实际代码让我们认为这是由bison自动生成的,所以我们想知道它是否应该始终有效以及编译器是否应该使用memmove或其他允许重叠的东西..]
答案 0 :(得分:3)
结构分配完全合法。因此编译器将生成正确的代码(尽管编译器错误)。
答案 1 :(得分:1)
这对我来说非常有用。是的,这将产生一种memcpy
。
两个指向struct
的指针应该只是相同或根本不重叠。因此,您可以在之前检查指针是否相等。
(你当然可以欺骗你的代码以实现真正的重叠,但必须有一个非常特殊的理由来做到这一点。)
答案 2 :(得分:0)
这是有效的代码。编译器不能假设x!= y,所以它必须使用安全memmove。
答案 3 :(得分:0)
[是的,回答我自己的问题,因为我在看了一下这个标准之后看到了这个问题并在这里更加努力地寻找相关问题]
实际上,Are there any platforms where using structure copy on an fd_set (for select() or pselect()) causes problems?(this answer)的部分回答可以回答这个问题,我将在此处粘贴:
以下其中一项应成立:
...
左操作数具有与右侧类型兼容的结构或联合类型的限定或非限定版本;
...
如果从另一个以第一个对象的存储方式重叠的对象读取存储在对象中的值,则重叠应该是精确的,并且这两个对象应具有兼容类型的合格或不合格版本;否则,行为未定义。
因此,只要指针是相同的(即总重叠),那么这很好。尽管memcpy的规范说不允许重叠,但编译器有时会为此插入对memcpy的调用,这似乎很奇怪。也许编译器更多地了解memcpy的特定实现,而不是文档所包含的...