相同地址的 C 结构体赋值有效吗?

发布于 2024-10-12 22:19:58 字数 356 浏览 7 评论 0原文

如果我的代码中有这样的内容:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一身仙ぐ女味 2024-10-19 22:19:58

结构分配是完全合法的。因此编译器将生成正确的代码(尽管存在编译器错误)。

Structure assignment is perfectly legal. Therefore the compiler will generate the correct code (compiler bugs notwithstanding).

感性不性感 2024-10-19 22:19:58

这对我来说看起来完全有效。是的,这将产生某种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.)

吃→可爱长大的 2024-10-19 22:19:58

这是有效的代码。编译器不能假设 x != y,因此必须使用安全 memmove。

This is valid code. The compiler can not assume x != y, so it must use safe memmove.

给我一枪 2024-10-19 22:19:58

[是的,回答我自己的问题,因为我在稍微查看了标准并在此处更努力地搜索相关问题后看到了这个问题]

实际上,这是由 是否有任何平台在 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:

One of the following shall hold:

...

the left operand has a qualified or unqualified version of a structure or union type compatible with the type of the right;

...

If the value being stored in an object is read from another object that overlaps in any way the storage of the first object, then the overlap shall be exact and the two objects shall have qualified or unqualified versions of a compatible type; otherwise, the behavior is undefined.

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..

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文