由未定义的C ++移位运算符行为和包装“模式空间” [英] Confused by undefined C++ shift operator behavior and wrapping "pattern space"

查看:223
本文介绍了由未定义的C ++移位运算符行为和包装“模式空间”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对在关于未定义C ++行为的文章


在ARM架构上,移位运算符总是表现为它们发生在256位模式空间中,而不管操作数大小 - 即模式重复或循环只有每256个位置。另一种思考方式是,模式以指定的位数模式256移位。然后,当然,结果只包含模式空间的最低有效位。




表特别奇怪:

 给定一个32位整数值为1:
+ ----------------------------------- +
| Shift left ARM x86 x64 |
+ ----------------------------------- +
| 32 0 1 1 |
| 48 0 32768 32768 |
| 64 0 1 1 |
+ ----------------------------------- +



这些值是什么,为什么重要?



=http://msdn.microsoft.com/en-us/library/336xbhcz =nofollow> shift操作符不换行。 根据C ++规范,如果你将一个32位的值向左移动32,结果总是为0. (编辑:我错了,看看答案!)那么这篇文章是什么?



当我在x86上运行这个代码时,我得到 0

  printf(%d,1 <32); 

假设此代码段说明了问题:

  // C4293.cpp 
// compile with:/ c / W1
unsigned __int64 combine(unsigned lo,unsigned hi){

return(hi< lo; // C4293

//尝试以下行
// return((unsigned __int64)hi<< 32)| lo;
}



我希望返回的值是 lo ,因为程序员移走了所有的 hi 位。警告是好的,因为这可能是一个错误,但我没有看到任何未定义的行为...

解决方案

您使用x86或x64机器指令来移位值,它们将屏蔽移位量,并仅使用较低的位用于实际移位。一些其他硬件可能不会这样做。



这是为什么它是未定义的。



code> 1<< 32 ,编译器可能会计算该值,这就是为什么它 0 。尝试在真正的x86硬件上的操作,你会得到 1


I'm confused by something I read in the Shift Operators section of an article on undefined C++ behavior.

On the ARM architecture, the shift operators always behave as if they take place in a 256-bit pattern space, regardless of the operand size--that is, the pattern repeats, or "wraps around", only every 256 positions. Another way of thinking of this is that the pattern is shifted the specified number of positions modulo 256. Then, of course, the result contains just the least-significant bits of the pattern space.

The tables are especially strange:

Given a 32-bit integer with a value of 1:
+-----------------------------------+
| Shift left    ARM    x86    x64   |
+-----------------------------------+
| 32            0      1      1     |
| 48            0      32768  32768 |
| 64            0      1      1     |
+-----------------------------------+

What are these values, and why do they matter?

The shift operators don't wrap. According to the C++ specification if you shift a 32-bit value left by 32, the result is always 0. (EDIT: I'm wrong, see the answers!) So what is this article getting at? What is the undefined behavior?

When I run this code on x86 I get 0:

printf("%d", 1 << 32);

Supposedly this code snippet illustrates the problem:

// C4293.cpp
// compile with: /c /W1
unsigned __int64 combine (unsigned lo, unsigned hi) {

    return (hi << 32) | lo;   // C4293

    // try the following line instead
    // return ( (unsigned __int64)hi << 32) | lo;
}

I would expect the returned value to be lo, since the programmer shifted away all the hi bits. A warning is nice, since this was probably a mistake, but I don't see any undefined behavior...

解决方案

If you use the x86 or x64 machine instructions for shifting the value, they will mask off the shift amount and only use the lower bits for the actual shift. Some other hardware might not do that.

That's why it is undefined.

In your example with literals 1 << 32, it is likely that the compiler computes the value and that's why it is 0. Trying the operation on real x86 hardware, you would get 1.

这篇关于由未定义的C ++移位运算符行为和包装“模式空间”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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