算术右移给出虚假结果?

Arithmetic right shift gives bogus result?(算术右移给出虚假结果?)
本文介绍了算术右移给出虚假结果?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

我一定是疯了,但是我机器上的 gcc 4.7.3 给出了最荒谬的结果.这是我正在测试的确切代码:

I must be absolutely crazy here, but gcc 4.7.3 on my machine is giving the most absurd result. Here is the exact code that I'm testing:

#include <iostream>

using namespace std;

int main(){
  unsigned int b = 100000;
  cout << (b>>b) << endl;
  b = b >> b;
  cout << b << endl;
  b >>= b;
  cout << b << endl;
  return 0;
}

现在,任何自行右移的数字都应该导致 0 (n/(2^n) == 0整数除法n>1positive/unsigned),但不知何故这是我的输出:

Now, any number that's right shifted by itself should result in 0 (n/(2^n) == 0 with integer divide, n>1, and positive/unsigned), but somehow here is my output:

100000
100000
100000

我疯了吗?可能会发生什么?

Am I crazy? What could possibly be going on?

推荐答案

在 C++ 中与在 C 中一样,移位仅限于移位值的大小(以位为单位).例如,如果 unsigned int 是 32 位,那么超过 31 位的移位是未定义的.

In C++ as in C, shifts are limited to the size (in bits) of the value shifted. For instance, if unsigned int is 32 bits, then a shift of more than 31 is undefined.

在实践中,一个常见的结果是使用移位量的最低5位,忽略高位;这是因为编译器生成了一条完全符合此要求的机器指令(例如 x86 上的 SHR).

In practice, a common result is that the 5 least-significant bits of the shift amount are used and the higher order bits are ignored; this is due to the compiler producing a machine instruction which does exactly that (eg SHR on x86).

在这种情况下,移位值是 100000(十进制),恰好是二进制的 11000011010100000 - 低 5 位为零.所以,你实际上得到了一个 0 的转变.但是你不应该依赖这个;从技术上讲,您看到的是未定义行为.

In this case, the shift value is 100000 (decimal) which happens to be 11000011010100000 in binary - the lower 5 bits are zero. So, you're effectively getting a shift by 0. You shouldn't rely on this however; technically, what you're seeing is undefined behaviour.

参考文献:

对于 C,N1570 6.5 节.7:

For C, N1570 section 6.5.7:

如果右操作数的值为负或大于或等于提升的左操作数的宽度,行为是未定义.

If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.

对于 C++,N3690第 5.8 节[expr.shift]":

For C++, N3690 section 5.8 "[expr.shift]":

如果右操作数为负数或更大,则行为未定义大于或等于提升的左操作数的位长度.

The behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand.

N1570 是一个草案,与已发布的 ISO C11 标准几乎相同;该条款自 1989 年 ANSI C 标准以来几乎相同.

N1570 is a draft, nearly identical to the released ISO C11 standard; this clause has been pretty much the same since the 1989 ANSI C standard.

N3690 是 C++ 标准的最新草案;我不确定它是否是最好用的,但同样,这个条款没有改变.

N3690 is a recent draft of the C++ standard; I'm not sure whether it's the best one to use, but again, this clause hasn't changed.

这篇关于算术右移给出虚假结果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

相关文档推荐

Prevent class inheritance in C++(防止 C++ 中的类继承)
Why should I declare a virtual destructor for an abstract class in C++?(为什么要在 C++ 中为抽象类声明虚拟析构函数?)
Why is Default constructor called in virtual inheritance?(为什么在虚拟继承中调用默认构造函数?)
C++ cast to derived class(C++ 转换为派生类)
C++ virtual function return type(C++虚函数返回类型)
Is there any real risk to deriving from the C++ STL containers?(从 C++ STL 容器派生是否有任何真正的风险?)