【问题标题】:Is left shifting unsigned int more than its bit field width, but less than its type size undefined?左移 unsigned int 是否大于其位域宽度,但小于其未定义的类型大小?
【发布时间】:2022-08-04 00:26:03
【问题描述】:
struct Type {
    uint8_t var : 3;
};

int main()
{
    struct Type bar;
    bar.var = 1;
    uint8_t baz = bar.var << 5;
}

根据标准,左移超过左操作数类型的宽度是未定义的行为:

6.5.7 移位运算符/3对每个操作数执行整数提升。结果的类型是提升的左操作数的类型。如果右操作数的值为负数或大于或等于提升的左操作数的宽度,则行为未定义。

但是位域呢?这里不是至少八位吗?

  • bar.var 将在轮班发生之前晋升为 int,因此没有 UB。不知道是否有一个普遍的答案
  • AFAIK 位域的内存布局是实现定义的,所以无论如何移位都不能保证给出正确的结果
  • 我在uint32_t baz = bar.var &lt;&lt; 9 上尝试了 gcc 12 并得到了 512,因此它提升到的不仅仅是左操作数类型。
  • 有趣的是,我在这里尝试了 clang 和 gcc:godbolt.org/z/bczqTeT78 直接在位域上移动了 3 位,您可以看到移位是在 16 位寄存器中完成的,结果被 & 0x7 截断为 3 位。所以至少那些编译器有一个或多或少按预期工作的实现。位被移出以永远丢失。 (仍然不排除实现特定的行为)

标签: c++ c undefined-behavior


【解决方案1】:

提升的左操作数的宽度(int 的宽度)至少为 16。5 远小于 16,因此定义了移位的行为。

【讨论】:

    猜你喜欢
    • 2023-03-27
    • 2013-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-10
    • 1970-01-01
    • 1970-01-01
    • 2021-11-16
    相关资源
    最近更新 更多