布尔类型的左移和右移操作

3

我试图理解算术移位运算符与积分提升的确切工作原理。特别是,我想知道在C++14标准中哪些值 a,b,c,d,e,f,g,h 是完全定义的,哪些可以取决于平台/硬件/编译器(假设sizeof(int) == 4)。

int a = true << 3;
int b = true >> 3;

int c = true << 3U;
int d = true >> 3U;

int e = true << 31;
int f = true >> 31;

int g = true << 31U;
int h = true >> 31U;

可能是重复问题:在C中使用位运算符进行布尔运算 - Thomas Matthews
@ThomasMatthews,你链接的问题根本没有讨论位移。 - Winter
2个回答

3

来自 [expr.shift]:

结果的类型与左操作数一样。如果右操作数为负数,或大于等于左操作数的位长度,则行为未定义。

bool 左移的结果类型始终为 int,无论右边是什么。我们从不左移至少 32 或负数,所以在所有方面都没问题。

对于左移 (E1 << E2):

否则,如果 E1 具有带符号类型和非负值,并且 E1×2E2 可以用结果类型的相应无符号类型表示,则该值转换为结果类型后即为结果值;否则,行为未定义。

1×231 可以用 unsigned int 表示,而这是我们进行的最大左移操作,因此在所有方面都没问题。

对于右移 (E1 >> E2):

如果 E1 具有带符号类型和负值,则结果值由实现定义。

E1 永远不会为负数,所以也没有任何未定义或实现定义的行为。


0

以下主要是对Barry的回答进行补充,明确解释了左移和右移的规则。

至少在C++11中,bool类型的整数提升会将false转换为0,将true转换为1:4.5 Integral promotions [conv.prom] § 6

bool类型的prvalue可以转换为int类型的prvalue,其中false变为零,true变为一。

因此,在原始示例中,bdfh都将获得0值,ac都将获得8值:直到这里只有完全定义的行为。

但是,eg将接收无符号值0x80000000,因此如果将其分配给无符号int变量,则可以正常使用,但是您正在使用带符号32位整数。因此,您会得到一个整数转换:4.7 Integral conversions [conv.integral] §3

如果目标类型是有符号的,并且该值可以在目标类型中表示,则该值保持不变;否则,该值由实现定义。
而无符号的0x80000000在有符号的64位整数中不能表示,因此eg的结果为实现定义

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接