tim*_*xd7 6 c++ bit-shift compiler-optimization integer-promotion c++17
我遇到了一个奇怪的问题,但为了清楚起见,先看代码:
#include <stdio.h>
#include <stdint.h>
int main() {
uint8_t a = 0b1000'0000; // -> one leftmost bit
uint8_t b = 0b1000'0000;
a = (a << 1) >> 1; // -> Both shifts in one line
b = b << 1; // -> Shifts separated into two individual lines
b = b >> 1;
printf("%i != %i", a, b);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
(在 x86 机器上使用 C++ 17)
如果编译代码,b则 is 0while ais 128。一般来说,这个表达式不应与处理器架构或其位宽相关,我希望两者都在0操作之后
位右移运算符定义为用零填充左侧位,如示例所示b。
如果我查看汇编代码,我可以看到对于b,值从 RAM 加载到寄存器中,左移,写回 RAM,再次从 RAM 读入寄存器,然后移位写入。每次写回 RAM 时,都会截断为 8 位整数,1从字节中删除最左边的部分,因为它超出了 8 位整数的范围。
另一方面a,该值被加载到寄存器中(基于x86架构,32位宽),左移,然后再次右移,将1移回到原来的位置,这是由32位寄存器引起的。
我现在的问题是,这是针对正确行为的单行优化吗a?在编写代码时应该考虑到这一点,还是要向编译器开发人员报告一个编译器错误?
dbu*_*ush 15
您看到的是整数提升的结果。这意味着(在大多数情况下)表达式使用小于 的类型的任何地方int,该类型都会提升为int。
C++17标准的 7.6p1 节对此进行了详细说明:
bool除、char16_t、 、以外的整数类型的纯右值char32_t,或者wchar_t其整数转换等级 (7.15) 小于 的等级 的纯右值,如果可以表示源类型的所有值,则int可以转换为该类型的纯右值;否则,源纯右值可以转换为类型的纯右值intintunsigned int
所以在这个表达式中:
a = (a << 1) >> 1
Run Code Online (Sandbox Code Playgroud)
a右侧的值从uint8_t值 0x80 提升到int值 0x00000080。左移一位得到 0x00000100,然后再次右移得到 0x00000080。然后,该值会被截断为 a 的大小,以便在将其分配回 时uint8_t给出。0x80a
在这种情况下:
b = b << 1;
Run Code Online (Sandbox Code Playgroud)
同样的事情开始发生:0x80 提升为 0x00000080,移位后得到 0x00000100。然后该值在分配给 之前被截断为 0x00 b。
所以这不是一个错误,而是预期的行为。
| 归档时间: |
|
| 查看次数: |
173 次 |
| 最近记录: |