c++ - 编译器是否优化了净零位移位?

标签 c++ c compilation compiler-optimization clang++

我在 .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 or unsigned int may be used:

  • An object or expression with an integer type (other than int or unsigned int) whose integer conversion rank is less than or equal to the rank of int and unsigned int.
  • A bit-field of type _Bool, int, signed int, or unsigned 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 an int; otherwise, it is converted to an unsigned 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/

相关文章:

JavaFX:为什么无论我传递给 `changeListener`什么样的 `textArea.getKeyPressedProperty().addListener`都无法编译

c++ - Unresolved external (抽象类构造函数/析构函数)

C++ 库包含防护

c - 命名管道和 fork 头痛

c - sigaction - 为什么我们不必重置处理程序?

javascript - 为什么节点编译比那样大?

C++ copy c'tor 现在开始行动了。不清楚为什么

C++11 线程,它是有效代码吗?

C - 将结构成员的地址传递给函数错误返回

c - 是否可以在 FreeBSD 中使用 ubuntu 的共享对象库?