意外的C / C ++按位移位运算结果 [英] Unexpected C/C++ bitwise shift operators outcome

查看:139
本文介绍了意外的C / C ++按位移位运算结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想我会疯了这一点。

我有一块AA code的需要来创建一个(无符号)整数, N 设置为1。准确的说我有一个位掩码随之位,而且在某些情况下,我想将它设置为一个坚实rnage。

I have a a piece of code that needs to create an (unsigned) integer with N consequent bits set to 1. To be exact I have a bitmask, and in some situations I'd like to set it to a solid rnage.

我有以下功能:

void MaskAddRange(UINT& mask, UINT first, UINT count)
{
    mask |= ((1 << count) - 1) << first;
}

在简单的话: 1 LT;&LT;计数二进制重新presentation是 100 ... 000 (零数为计数),从这样的数减去1给出了 011 ... 111 ,然后我们刚离开移通过第一

In simple words: 1 << count in binary representation is 100...000 (number of zeroes is count), subtracting 1 from such a number gives 011...111, and then we just left-shift it by first.

上面应产生正确的结果,当满足下列明显的限制被满足:

The above should yield correct result, when the following obvious limitation is met:

第一+计数&LT; = sizeof的(UINT)* 8 = 32

注意,它的的还正确的极端的情况下工作。

Note that it should also work correctly for "extreme" cases.


  • 如果计数= 0 我们(1 LT;&LT;计数)= 1 ,因此,((1 <<;&LT;计数) - 1)= 0

  • 如果数= 32 我们(1 LT;&LT;计数)= 0 ,因为前导位溢出,并根据C / C ++规则按位移位运算符的不循环。然后((1 <<;&LT;计数) - 1)= -1 (所有位设置)

  • if count = 0 we have (1 << count) = 1, and hence ((1 << count) - 1) = 0.
  • if count = 32 we have (1 << count) = 0, since the leading bit overflows, and according to C/C++ rules bitwise shift operators are not cyclic. Then ((1 << count) - 1) = -1 (all bits set).

不过,正如横空出世,为数= 32 如预期公式不起作用。由于发现的:

However, as turned out, for count = 32 the formula doesn't work as expected. As discovered:

UINT n = 32;
UINT x = 1 << n;
// the value of x is 1

此外,我使用MSVC2005 IDE。当我在调试器评估上述前pression,结果为0。然而,当我跨过上面一行, X 获得通过1 Lokking价值反汇编,我们看到以下内容:

Moreover, I'm using MSVC2005 IDE. When I evaluate the above expression in the debugger, the result is 0. However when I step over the above line, x gets value of 1. Lokking via the disassembler we see the following:

mov eax,1 
mov ecx,dword ptr [ebp-0Ch] // ecx = n
shl eax,cl                  // eax <<= LOBYTE(ecx)
mov dword ptr [ebp-18h],eax // n = ecx

有什么神奇事实上,编译器只是用 SHL 指令。然后,它似乎 SHL 并没有做什么,我估计它应该做的。无论是CPU决定忽略这个指令或移位处理模32或唐诺什么。

There's no magic indeed, compiler just used shl instruction. Then it seems that shl doesn't do what I expected it should do. Either CPU decides to ignore this instruction, or the shift is treated modulo 32, or donno what.

我的问题是:


  • 什么是 SHL / SHR 指示正确的行为?

  • 有一个CPU标志控制bitshift说明?

  • 这是根据C / C ++标准?

  • What is the correct behavior of shl/shr instructions?
  • Is there a CPU flag controlling the bitshift instructions?
  • Is this according to C/C++ standard?

在此先感谢

编辑:

感谢您的答案。我已经意识到(1) SHL / SHR 确实把操作数模32(或放大器; 0x1F的)和( 2)C / C ++标准治疗超过31位的未定义的行为转变。

Thanks for answers. I've realized that (1) shl/shr indeed treat operand modulo 32 (or & 0x1F) and (2) C/C++ standard treats shift by more than 31 bits as undefined behavior.

然后,我有一个问题。我怎么可以重写我的屏蔽前pression过于掩盖这种极端情况。它应该是没有分支(如果)。什么了是最简单的前pression?

Then I have one more question. How can I rewrite my "masking" expression to cover this extreme case too. It should be without branching (if, ?). What'd be the simplest expression?

推荐答案

1U&LT;&LT; 32 在C和C ++中未定义行为时,键入 unsigned int类型是32位宽。

1U << 32 is undefined behavior in C and in C++ when type unsigned int is 32-bit wide.

(C11,6.5.7p3)如果右操作数的值是负的或大于或等于促进左操作数的宽度,该行为是未定义

(C11, 6.5.7p3) "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 ++ 11,5.8p1)的行为是不确定如果右操作数是负的,或者大于或等于在推动左操作数的位长度。

(C++11, 5.8p1) "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."

这篇关于意外的C / C ++按位移位运算结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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