C语言 工会的原子成员是个好主意吗?

2ic8powd  于 2023-11-16  发布在  其他
关注(0)|答案(1)|浏览(121)

我在联合体中使用_Atomic整数,例如:

union dedup_option_seq {
    struct {
        uint32_t seq       :18;     // 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成员的联合时,我会导致任何未定义的行为或其他问题吗?

7y4bm7vi

7y4bm7vi1#

这一切都工作得很好,但是当使用带有_Atomic成员的联合时,我会导致任何未定义的行为或其他问题吗?
C允许你读回一个联合体中不同于上次设置的成员。这在C中是可以的(但在C++中不行)。C不会根据所涉及类型的限定符(如_Atomic)来限制这一点,所以这不是一个直接的问题。
然而,在这方面,

  • _Atomic类型不能保证与对应的非_Atomic类型具有相同的大小或表示,
  • struct中位域的布局比您想象的要少得多。

在这两者之间,C允许你的例子,

  • value的表示可能不会与seqnot_empty的表示全部重叠。在不重叠的实现中,您尝试通过value原子地操作这些位不会产生预期的效果。
  • 即使valueseqnot_empty完全重叠,后两者的某些位可能与前者的值位不对应。在这种情况下,您尝试通过value原子地操作这些位可能不会产生预期的效果。
  • 即使普通的uint32_t没有任何陷阱表示,但将seq和/或not_empty转换为value可能会导致value包含陷阱表示。在可能出现这种情况的实现中,尝试通过value原子地操作这些位可能会导致陷阱,可能会导致程序崩溃。是否以及何时发生可能取决于数据。

此外,通过联合体的其他成员非原子地操作_Atomic对象value似乎是令人担忧的。至少,这样的操作不享受直接操作value所提供的任何原子性保证。
那么这里是否存在未定义的行为呢?很难说。关于语言规范没有直接处理的行为,肯定有一些问题。其中一些或全部可能更好地描述为未定义而不是未定义,但如果你要求你的程序在不同的C实现上可重复地产生相同的结果,前者并不比后者好多少。

相关问题