布尔值的左移和右移

Left shifts and right shifts on boolean

本文关键字:右移 左移 布尔值      更新时间:2023-10-16

我正试图理解积分提升是如何与算术移位操作符一起工作的。特别是,我想知道a, b, c, d, e, f, g, h的哪些值是根据c++ 14标准精确定义的,哪些值可以依赖于平台/硬件/编译器(假设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;

From [exp .shift]:

操作结果的类型为提升后的左操作数的类型。如果操作数为右,则行为未定义

为负数,或大于或等于提升后左操作数的位长度。

移动一个bool的结果类型总是int,不管右边是什么。我们不会移动至少32或一个负数,所以总的来说是可以的。

对于左移(E1 <<E2):

否则,如果E1是有符号类型且非负值,且E1×2E2是可表示的在结果类型的相应unsigned类型中,则该值转换为结果类型后为得到的值;否则,行为是未定义的。

1×231unsigned int表示,这是我们正在做的最大的左移,所以我们在所有帐户上都没问题。

对于右移(E1>> E2):

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

E1永远不会是负的,所以我们也没问题!没有未定义或实现定义的行为。

以下主要是对Barry的回答的补充,清楚地解释了左右移动的规则。

至少在c++ 11中,bool值的整型提升对于false是0,对于true是1:

bool类型的右值可以转换为int类型的右值,false为0,true为1。

所以在原始示例中,b, d, fh都将获得0值,ac都获得8值:直到这里才完全定义行为。

但是eg将接收无符号值0x80000000,所以如果您将其影响为无符号int变量,但是您使用的是有符号32位整数。所以你得到一个积分转换: 4.7积分转换[conv_integral]§3

如果目标类型是有符号的,如果该值可以用目标类型表示,则该值不变;否则,该值为实现定义。

和无符号0x80000000在有符号的64位整数中是不可表示的,所以结果是实现为eg定义的