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以下内容可用于任何地方
int或unsigned int可能使用的表达方式:
- 一个整型(比其它的对象或表达
int或unsigned int),其整数转换秩小于或等于的秩int和unsigned 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进行存储.