【问题标题】:Left shifts and right shifts on boolean布尔值的左移和右移
【发布时间】:2016-01-11 15:52:45
【问题描述】:

我正在尝试了解积分提升如何与算术移位运算符一起使用。特别想知道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;

【问题讨论】:

标签: c++ standards c++14 bit-shift integer-promotion


【解决方案1】:

来自 [expr.shift]:

结果的类型是提升的左操作数的类型。如果正确的操作数,则行为未定义 为负数,或大于或等于提升的左操作数的位长度。

移动bool 的结果类型始终为int,无论右侧是什么。我们永远不会改变至少 32 或负数,所以我们在所有方面都很好。

对于左移(E1

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

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

对于右移(E1 >> E2):

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

E1 永远不会是负数,所以我们也可以!任何地方都没有未定义或实现定义的行为。

【讨论】:

    【解决方案2】:

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

    至少对于 C++11,bool 的积分提升为 false 给出 0,对于 true 给出 1:4.5 积分提升 [conv.prom] § 6

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

    所以在原始示例中,b、d、f 和 h 都将获得 0 值,a 和 c 都获得 8 值:只有完美定义的行为,直到在这里。

    但是e 和g 将收到无符号值0x80000000,所以如果你将它影响到一个无符号的int 变量就可以了,但是你使用的是有符号的32 位整数。所以你得到一个积分转换:4.7 积分转换 [conv.integral] §3

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

    并且无符号的 0x80000000 不能用有符号的 64 位整数表示,因此结果是 为e 和 g 定义的实现。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-18
      相关资源
      最近更新 更多