位域和序列点

发布于 2025-01-02 06:42:21 字数 468 浏览 0 评论 0原文

对于将 f0f1 打包到同一字节的实现,下面的程序是否已定义?

struct S0 {
       unsigned f0:4;
       signed f1:4;
} l_62;

int main (void) {
       (l_62.f0 = 0) + (l_62.f1 = 0);
       return 0;
}

如果有理由认为 C99 和 C11 的答案有所不同,我对 C99 和 C11 的答案感兴趣。

在C99中,我发现的只是6.5:2:

在上一个和下一个序列点之间,对象应有其 存储的值最多被表达式的求值修改一次。 [...]

我不清楚这一段对上面的程序有什么影响。

根据大量随机测试,大多数编译器似乎生成的代码中两个赋值互不干扰。

For an implementation that packs f0 and f1 into the same byte, is the program below defined?

struct S0 {
       unsigned f0:4;
       signed f1:4;
} l_62;

int main (void) {
       (l_62.f0 = 0) + (l_62.f1 = 0);
       return 0;
}

I am interested in the answer for C99 and for C11 if there is reason to think that it is different there.

In C99, all I found was 6.5:2:

Between the previous and next sequence point an object shall have its
stored value modified at most once by the evaluation of an expression.
[...]

It is not clear for me what consequences this paragraph has on the program above.

Based on a large number of randomized tests, most compilers appear to generate code where the two assignments do not interfere.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(2

晌融 2025-01-09 06:42:21

C11 将相邻的命名位字段视为同一内存位置的一部分。此类位字段不保证以原子方式更新,换句话说,如果一个更新未在另一个更新之前显式排序,则行为未定义。 3.14内存位置还详细解释了何时可以认为两个字段位于不同的内存位置,因此可以独立考虑对它们的更新。

如果您修改您的结构

struct S0 {
       unsigned f0:4;
       int :0;
       signed f1:4;
} l_62;

,以便在两个位字段之间存在这种奇怪的“内存位置分隔符”,那么您的代码将保证没问题。

对于C99来说情况似乎更复杂,没有这么详细的内存位置概念。在最近关于 Linux 内核邮件列表的讨论中,有人声称,通常对于所有位字段对,在更新其中任何一个位字段时都会保证原子性。该讨论的出发点是 gcc 以意想不到的方式污染了与位字段相邻的非位字段,从而导致虚假崩溃。

C11 considers adjacent named bit fields to be part of the same memory location. Such bit fields are not guaranteed to be updated atomically, in other words if one update is not sequenced explicitly before the other the behavior is undefined. 3.14 memory location then also has a detailed explanation of when two fields can be considered being in different memory locations, thus updates to them can be considered independently.

If you would modify your structure

struct S0 {
       unsigned f0:4;
       int :0;
       signed f1:4;
} l_62;

such that there is this bizarre "memory location separator" between the two bit fields, your code would be guaranteed to be fine.

For C99 the case seems to be more complicated, there is not such a detailed concept of memory location. In a recent discussion on the linux kernel mailing list there was a claim that generally for all pairs of bit fields there would be a guarantee of atomicity when updating any of them. The starting point of that discussion was a case where gcc polluted a non-bit field neighboring a bit field in an unexpected way leading to spurious crashes.

—━☆沉默づ 2025-01-09 06:42:21

这里的赋值是给结构体成员的。它们碰巧共享相同的存储这一事实应该不会对逻辑产生影响。事实上,您实际上并没有对同一件事进行分配。

当然,我不是语言律师。

The assignment here is to the struct members. The fact that they happen to share the same storage should have no effect on the logic. You have not, in fact, actually made an assignment to the same thing.

Of course, I am not a language lawyer.

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