编译器是否优化出净零位移位? [英] Do compilers optimize out net zero bit shifts?

查看:58
本文介绍了编译器是否优化出净零位移位?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 .cpp 文件中有一些类似于以下代码块的代码(不允许张贴原始代码),我认为它是由 clang ++ 编译的( Ubuntu clang版本3.5.2-3ubuntu1(标签/RELEASE_352/final)(基于LLVM 3.5.2)).
看起来像 C 代码,因为我们正在使用 GoogleTest 来测试我们的 C 代码.无论如何:

I have some code like the following code block (I am not allowed to post the original code) inside a .cpp file that I think is being compiled by clang++ (Ubuntu clang version 3.5.2-3ubuntu1 (tags/RELEASE_352/final) (based on LLVM 3.5.2)).
It looks like C code, because we are using GoogleTest for testing our C code. Anyways:

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位被清零.但是我发现这是不对的.该程序只是恢复原始值.

Now, why does comment [1] hold true? I was assuming that the corresponding line would result in the top 4 bits being zeroed out. But I found out that this isn't true; the program simply restores the original value.

这是某种语言定义的行为,还是 clang 编译出了所谓的无用位移?

Is this some language defined behavior, or is clang compiling out a supposedly useless bit shift?

(我检查了关联性(假设使用此表在cppreference.com 上,基本操作符的关联性/优先级在 C ++ 的版本之间也不会有所不同,并且在 C ++ C 的版本之间也可能不会有所不同,至少在'当前版本"),似乎 [1] 处的RHS表达式应该确实产生与以下两个语句相同的结果)

(I checked associativity (using this table on cppreference.com, assuming that associativity/precedence of basic operators won't differ between versions of C++ and probably not between C++ and C either, at least not in 'current versions') and it seems like the RHS expression at [1] should really yield the same result as the two following statements)

推荐答案

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

What you are seeing is a result of integer promotions. Any value with a type of lower rank than int, when used in an expression, is promoted to int.

这在C标准

2 以下表达式可用于 int unsigned int 可能在的表达式中被使用:

2 The following may be used in an expression wherever an int or unsigned int may be used:

  • 具有整数类型( int unsigned int 除外)的对象或表达式其整数转换等级小于或等于 int 的等级,并且 unsigned int .
  • _Bool int signed int unsigned int 类型的位字段.
  • li>
  • 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.

如果 int 可以表示原始类型的所有值(受宽度限制,对于位字段),将值转换为 int ;否则,它将转换为 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 .

var is first promoted to int. This type is at least 16 bits wide, and most likely 32 bits wide. So the value being operated on is 0x00000018. A left shift of 4 results in 0x00000180, and subsequently right shifting results in 0x00000018.

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

The result is then stored in a uint_8. Since the value fits in a variable of this type, no conversion is required and 0x18 is stored.

这篇关于编译器是否优化出净零位移位?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆