布尔值的左移和右移
Left shifts and right shifts on boolean
我正试图理解积分提升是如何与算术移位操作符一起工作的。特别是,我想知道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×231由unsigned int
表示,这是我们正在做的最大的左移,所以我们在所有帐户上都没问题。
对于右移(E1>> E2):
如果E1具有带符号类型和负值,则结果值是实现定义的。
E1永远不会是负的,所以我们也没问题!没有未定义或实现定义的行为。
以下主要是对Barry的回答的补充,清楚地解释了左右移动的规则。
至少在c++ 11中,bool值的整型提升对于false
是0,对于true
是1:
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
定义的。
- 使用boost::multiprecision cpp_int左移时出现超时错误
- 警告:左移计数 >= 在 C++ 中将字节流读取为双精度变量时的类型宽度
- 左移<<如何在不同的功能中给出不同的结果?
- 使用 AVX2 指令左移 128 位数字
- <<(按位左移)在 Swift 中的数组上做什么?
- 带有左移操作员C 的意外输出
- 编译器将输出的流运算符<<解释为用于按位左移的二进制运算符<<
- 左移负整数为零是否有意义?
- 在 VS 移位中,UINT64 上的左移(64 >移位> 32)位仅 32 位
- C++20 是否为"overflow"的有符号整数很好地定义了左移?
- C++左移操作
- 为什么编译器左移 0
- 如何在位明智的操作中选择正确的左移
- 为什么很多人使用左移<<而不是乘法
- 左移 0 有什么意义
- 右移速度与左移相同的速度测试位
- 重载左移和右移运算符(cin和cout)
- 使用左移或右移计算对数基数 n
- 在C/C++中,左移或右移零点实际上会生成一条指令
- 布尔值的左移和右移