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

pol*_*nut 7 c c++ compilation compiler-optimization clang++

我有一些代码,如下面的代码块(我不允许发布原始代码)在.cpp我认为由clang++(Ubuntu clang version 3.5.2-3ubuntu1 (tags/RELEASE_352/final) (based on 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)
Run Code Online (Sandbox Code Playgroud)

现在,为什么评论[1]成立?我假设相应的行会导致前4位被清零.但我发现这不是真的; 该程序只是恢复原始值.

这是一些语言定义的行为,还是clang编译出一个无用的位移?

(我检查了关联性(在cppreference.com上使用这个表,假设基本运算符的关联性/优先级在版本之间不会有差异C++,可能不在C++和之间C,至少不在'当前版本')并且看起来像RHS表达式at [1]应该真正产生与以下两个语句相同的结果)

dbu*_*ush 11

您所看到的是整数促销的结果.int当在表达式中使用时,具有低于等级的类型的任何值被提升为int.

这在C标准的 6.3.1.1节中有详细说明

2以下内容可用于任何地方intunsigned int可能使用的表达方式:

  • 一个整型(比其它的对象或表达intunsigned int),其整数转换秩小于或等于的秩intunsigned int.
  • 类型的位字段_Bool,int,signed int,或unsigned int.

如果a int可以表示原始类型的所有值(由宽度限制,对于位字段),则该值将转换为int; 否则,它被转换为unsigned int.这些被称为整数促销.整数促销不会更改所有其他类型.

在这种情况下:

var = var << SHIFT >> SHIFT;
Run Code Online (Sandbox Code Playgroud)

var首先被提升为int.此类型至少为16位宽,最可能为32位宽.所以正在运作的价值是0x00000018.左移4导致0x00000180,随后右移导致0x00000018.

然后将结果存储在a中uint_8.由于该值适合此类型的变量,因此不需要进行转换并0x18进行存储.

  • @polynomial_donut这是*不正确,因为1)`size_t`可能大于`unsigned int`,2)标准特别声明提升值的类型是`int`. (2认同)