用C右移负数 [英] Right shifting negative numbers in C

查看:192
本文介绍了用C右移负数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对C code中,我做到以下几点。

  INT nPosVal = + 0xFFFF的; // +增加了便于理解
INT nNegVal = -0xFFFF; // - 增加了对正当的理由

现在,当我尝试

 的printf(%D,nPosVal>> 1,nNegVal>> 1);

我得到

  32767 -32768

时这正常吗?

我能认为像

  65535>> 1 =(INT)32767.5 = 32767
-65535>> 1 =(INT)-32767.5 = -32768

这就是-32767.5四舍五入-32768。

这是理解是否正确?


解决方案

它看起来像你的实现是可能做有两个的补数算术移位。在这个系统中,所有位向右移动到右侧的,然后在与复制任何的最后一个比特是高位比特填充。因此,对于你的榜样,对待INT如下32位的:

  nPosVal = 00000000000000001111111111111111
nNegVal = 11111111111111110000000000000001

移位后,你有:

  nPosVal = 00000000000000000111111111111111
nNegVal = 11111111111111111000000000000000

如果您转换这回小数,你得分别为32767和-32768。

实际上,右移舍入到负无穷大。

编辑:据该科最新的标准草案,关于负数这种行为是依赖于实现:

E1 >> E2的结果是E1右移E2位的位置。如果E1有一个无符号类型,或者如果E1有一个签名的类型和一个非负值,则结果的值是E1 / 2 E2 的商的整数部分。如果E1有一个签名的类型和负值,所得到的值是实现定义

他们既定的理性:

的C89在不要求签名的右移位操作符号扩展,因为这样的要求可能会拖慢速度快code和因为符号扩展变化的用处是微不足道的 - [R;委员会肯定了K&放授予实施的自由。 (移的负二的补
整数算术正确的地方是不会的同除以二!)

所以,它的实现依赖于理论。在实践中,我从来没有见过一个执行不会的做算术右移时,左边的操作数签署。

I have C code in which I do the following.

int nPosVal = +0xFFFF;   // + Added for ease of understanding
int nNegVal = -0xFFFF;   // - Added for valid reason

Now when I try

printf ("%d %d", nPosVal >> 1, nNegVal >> 1);

I get

32767 -32768

Is this expected?

I am able to think something like

65535 >> 1 = (int) 32767.5 = 32767
-65535 >> 1 = (int) -32767.5 = -32768

That is, -32767.5 is rounded off to -32768.

Is this understanding correct?

解决方案

It looks like your implementation is probably doing an arithmetic bit shift with two's complement numbers. In this system, it shifts all of the bits to the right and then fills in the upper bits with a copy of whatever the last bit was. So for your example, treating int as 32-bits here:

nPosVal = 00000000000000001111111111111111
nNegVal = 11111111111111110000000000000001

After the shift, you've got:

nPosVal = 00000000000000000111111111111111
nNegVal = 11111111111111111000000000000000

If you convert this back to decimal, you get 32767 and -32768 respectively.

Effectively, a right shift rounds towards negative infinity.

Edit: According to the Section 6.5.7 of the latest draft standard, this behavior on negative numbers is implementation dependent:

The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.

Their stated rational for this:

The C89 Committee affirmed the freedom in implementation granted by K&R in not requiring the signed right shift operation to sign extend, since such a requirement might slow down fast code and since the usefulness of sign extended shifts is marginal. (Shifting a negative two’s complement integer arithmetically right one place is not the same as dividing by two!)

So it's implementation dependent in theory. In practice, I've never seen an implementation not do an arithmetic shift right when the left operand is signed.

这篇关于用C右移负数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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