相同地址的 C 结构体赋值有效吗?
如果我的代码中有这样的内容:
void f(struct foo *x, struct foo *y)
{
*x = *y; // structure copy (memcpy?)
}
如果 x 和 y 指向同一地址,会发生什么?
这是有效的代码吗?如果编译器将赋值转换为具有潜在无效操作数(不允许重叠)的 memcpy 调用会怎样?
[是的,我知道在这种情况下我可以使用“restrict”,但是我们发现的实际代码让我们认为这是由 bison 自动生成的,所以我们想知道它是否应该始终有效以及编译器是否应该使用 memmove 或其他允许重叠的东西..]
If I have something like this in my code:
void f(struct foo *x, struct foo *y)
{
*x = *y; // structure copy (memcpy?)
}
If x and y point to the same address, what happens?
Is this valid code, and what if the compiler converts the assignment into a memcpy call with potentially-invalid operands (they aren't allowed to overlap)?
[Yes, I know I can use "restrict" in this case, but the actual code we found which made us consider this is automatically-generated by bison so we were wondering if it should always be valid and whether the compiler should use memmove or something else which allows overlap..]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
结构分配是完全合法的。因此编译器将生成正确的代码(尽管存在编译器错误)。
Structure assignment is perfectly legal. Therefore the compiler will generate the correct code (compiler bugs notwithstanding).
这对我来说看起来完全有效。是的,这将产生某种
memcpy
。像这样的两个指向 struct 的指针只能是相同的或根本不重叠。所以你可以在之前检查指针是否相等。
(您当然可以欺骗您的代码以实现真正的重叠,但必须有一个非常特殊的理由才能这样做。)
This looks perfectly valid to me. Yes, this will result in a sort of
memcpy
.Two pointers to
struct
like that should only either be the same or not overlap at all. So you could do a check if the pointers are equal, before.(You can certainly trick your code to have a real overlap, but there'd have to be a really special reason to do that.)
这是有效的代码。编译器不能假设 x != y,因此必须使用安全 memmove。
This is valid code. The compiler can not assume x != y, so it must use safe memmove.
[是的,回答我自己的问题,因为我在稍微查看了标准并在此处更努力地搜索相关问题后看到了这个问题]
实际上,这是由 是否有任何平台在 fd_set 上使用结构复制(用于 select () 或 pselect()) 会导致问题吗?(在 这个答案),我将粘贴在这里:
因此,只要指针相同(即完全重叠)就可以了。尽管 memcpy 的规范规定不允许重叠,但编译器有时会为此插入对 memcpy 的调用,这似乎仍然很奇怪。也许编译器比文档所回避的更了解 memcpy 的特定实现。
[Yes, answering my own question as I saw this after looking in the standard a bit and searching harder for related questions on here]
Actually, this is answered by part of the answer to Are there any platforms where using structure copy on an fd_set (for select() or pselect()) causes problems? (in this answer), which I will paste here:
Hence as long as the pointers are the same (i.e. total overlap) then this is fine. Still seems odd that the compiler inserts a call to memcpy sometimes for this despite the spec of memcpy saying that overlap is not allowed. Perhaps the compiler knows more about the particular implementation of memcpy than the documentation eludes to..