结构体赋值是否保证填充字段的相等?

6

假设我有一个有两个字段的结构体,我的C实现在这些字段之间也有一些填充。

如果我创建两个该结构体的变量,并将其中一个分配给另一个,那么填充是否保证相等?

我知道对于大多数编译器来说是这样的(因为它们只是调用memcpy),但我想知道标准中对填充的规定是什么?

提问的意图是,我能否使用 memcmp 检查结构体的相等性。

假设我有一个编译器,它发出的代码只是将结构体的所有成员赋值,而不是执行 memcpy ,那么它是否是结构体操作分配的有效实现?


1
你关心的是填充值,而不是大小,对吗? - Eugene Sh.
一般来说,填充内容不会是相同的。它似乎是未初始化的。在 x = y 的情况下,我认为填充是否相同取决于实现。 - BLUEPIXY
@EugeneSh。是的,填充值的大小将相同,因为它们是相同的结构体。 - Ajay Brahmakshatriya
@BLUEPIXY,那我不能使用memcmp来比较结构体的相等性吗? - Ajay Brahmakshatriya
最好认为你不能使用 memcmp - BLUEPIXY
3个回答

7

谢谢,这直接解决了问题。实际上,注释52也直接讨论了memcmp。但是它是关于==的。同样的想法。 - Ajay Brahmakshatriya
是的,52也很有趣。你认为应该添加吗? - Eugene Sh.
严格来说,这是关于结构体不支持“==”运算符的问题。但你可以额外添加它,可能会阐明其设计背后的动机。 - Ajay Brahmakshatriya
注意,周围有很多使用memcmp比较结构体,使用memcpy复制结构体和使用bzero清除结构体的旧代码 - 因此,即使标准说“你不需要”,大多数编译器仍会实现“精确”结构体的副本,因为它们根本无法承受破坏这些代码的代价。 - tofro

6
6.2.6.1 常规
...
6 当一个值被存储在结构体或联合类型的对象中,包括成员对象时,与任何填充字节对应的对象表示的字节都取未指定的值。51) 结构体或联合对象的值永远不是陷阱表示,尽管结构体或联合对象的成员的值可能是陷阱表示。

7 当一个值被存储在联合类型对象的成员中时,与该成员不对应但对应于其他成员的对象表示的字节都取未指定的值。
51) 因此,例如,结构分配不需要复制任何填充位。

C 2011在线草案

脚注51直接解答了你的问题 - 分配时不会复制填充位的内容,因此memcmp可能无法用于比较相等的两个structs


谢谢,这解决了我的问题。 - Ajay Brahmakshatriya
接受 @EugeneSh 的答案,因为他先回答了。 - Ajay Brahmakshatriya

1
我认为你不能使用memcmp,因为成员之间的内存(即“填充”区域中的内容)不能保证具有确定的值,并且将这样的结构对象分配给另一个对象时不需要复制填充内容。

我的直觉和你的一样,但由于这是一个[语言律师]问题,你需要提供标准的证明 :) - Quentin
所以基本上你的意思是,如果在一个带填充的结构体上调用memcmp函数,那么这将是未定义的行为,因为你试图读取未初始化的字节? - Ajay Brahmakshatriya
如果赋值右侧的struct是通过memset来初始化的呢? - Ajay Brahmakshatriya
@Quentin:没错 - 被孩子们打断了 :-) 后来一切都清楚了... - Stephan Lechner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接