我在联合内部使用 _Atomic 整数,例如:
union dedup_option_seq {
struct {
uint32_t seq :DEDUP_SHIFT; // enough bits for seq
uint32_t not_empty :1; // inverted so that zero is empty
};
_Atomic uint32_t value;
};
然后我可以愉快地使用
&foo.value
作为 atomic_...()
函数中的参数。
我可以使用语法设置联合的值:
union dedup_option_seq foo = {
.seq = 42,
.not_empty = 1
};
一切都工作得很好,但是当我与 _Atomic 成员一起使用联合体时,我是否会导致任何未定义的行为或其他问题?
一切都工作得很好,但是当我与 _Atomic 成员一起使用联合体时,我是否会导致任何未定义的行为或其他问题?
C 允许您读回联合体中与上次设置的成员不同的成员。这在 C 中是可以的(但在 C++ 中不行)。 C 不会根据所涉及类型的限定符(例如
_Atomic
)来限制这一点,因此这不是直接的问题。
但是,
_Atomic
类型与其对应的非 _Atomic
类型具有相同的大小或表示形式,并且
struct
中位域的布局比您想象的要少得多。
在这些之间,C 允许你的例子
value
的表示可能不会与seq
和not_empty
的整个表示重叠。在不这样做的实现中,您尝试通过 value
以原子方式操作这些位将不会达到您期望的效果。
即使
value
确实与整个seq
和not_empty
重叠,后两者的某些位也可能不对应于前者的值位。在这种情况下,您尝试通过 value
以原子方式操作这些位可能不会达到您预期的效果。
分配给
seq
和/或 not_empty
可能会导致 value
包含陷阱表示,即使普通 uint32_t
没有任何陷阱表示。在这种情况的实现中,尝试通过 value
以原子方式操作这些位可能会导致陷阱,可能导致程序崩溃。这种情况是否发生以及何时发生可能取决于数据。
此外,通过联盟的其他成员以非原子方式操作
_Atomic
对象value
似乎令人担忧。至少,此类操作不享有直接操作 value
所提供的任何原子性保证。
那么这里是否存在未定义的行为?很难说。肯定存在语言规范没有直接解决的行为问题。其中部分或全部可能比未定义更好地描述为未指定,但如果您需要您的程序在不同的 C 实现上可重复地产生相同的结果,则前者并不比后者好多少。