我在 .cpp
文件中有一些代码,如以下代码块(我不允许发布原始代码),我认为它是由 clang++
编译的(Ubuntu clang 版本 3.5.2-3ubuntu1 (tags/RELEASE_352/final)(基于 LLVM 3.5.2)
)。
它看起来像 C
代码,因为我们使用 GoogleTest
来测试我们的 C
代码。无论如何:
size_t const SHIFT = 4;
uint8_t var, var2;
/* Omitted: Code that sets var to, say 00011000 (base 2) */
var2 = var;
var = var << SHIFT >> SHIFT; // [1] result is 00011000 (base 2) (tested with printf)
var2 = var2 << SHIFT;
var2 = var2 >> SHIFT; // [2] result is 00001000 (base 2) (tested with printf)
现在,为什么评论 [1]
成立?我假设相应的行会导致前 4 位被清零。但我发现这不是真的;该程序只是恢复原始值。
Is this some language defined behavior, or is
clang
compiling out a supposedly useless bit shift?
(我检查了关联性(使用 this table on cppreference.com ,假设基本运算符的关联性/优先级在 C++
版本之间没有差异,并且可能在 C++
和 C
要么,至少在“当前版本”中没有)并且看起来 [1]
处的 RHS 表达式应该产生与以下两个语句相同的结果)
最佳答案
您看到的是整数提升的结果。任何级别低于 int
的值在表达式中使用时,都会被提升为 int
。
这在 C standard 的第 6.3.1.1 节中有详细说明
2 The following may be used in an expression wherever an
int
orunsigned int
may be used:
- An object or expression with an integer type (other than
int
orunsigned int
) whose integer conversion rank is less than or equal to the rank ofint
andunsigned int
.- A bit-field of type
_Bool
,int
,signed int
, orunsigned int
.If an
int
can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to anint
; otherwise, it is converted to anunsigned int
. These are called the integer promotions. All other types are unchanged by the integer promotions.
在这种情况下:
var = var << SHIFT >> SHIFT;
var
首先被提升为 int
。这种类型至少有 16 位宽,最有可能是 32 位宽。所以被操作的值是 0x00000018
。左移 4 导致 0x00000180
,随后右移导致 0x00000018
。
然后将结果存储在 uint_8
中。由于该值适合此类型的变量,因此不需要转换并存储 0x18
。
关于c++ - 编译器是否优化了净零位移位?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48775746/