【发布时间】: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 << 9上尝试了 gcc 12 并得到了 512,因此它提升到的不仅仅是左操作数类型。 -
有趣的是,我在这里尝试了 clang 和 gcc:godbolt.org/z/bczqTeT78 直接在位域上移动了 3 位,您可以看到移位是在 16 位寄存器中完成的,结果被 & 0x7 截断为 3 位。所以至少那些编译器有一个或多或少按预期工作的实现。位被移出以永远丢失。 (仍然不排除实现特定的行为)
标签: c++ c undefined-behavior