为了优化我的cpp代码,我尝试在某些情况下使用Right Shifting。这是一个例子:
int main()
{
int i = (1 - 2) >> 31; // sizeof(int) == 4
...
...
}
我打印了i
,我得到-1
。这意味着如果数字为负数,它将使用1
代替0
来填充空位置。换句话说,-1 >> 31
的工作原理如下:
1111...1 <--- the result of (1 - 2), which is -1
1111...1 <--- -1 >> 31, 1 is used to fill in the empty position
我只是想知道这种行为是否已明确定义?
如果在cpp中是UB,在Java中怎么样?
答案 0 :(得分:1)
是即可。它是实现定义的。
根据 C ++ 03 5.8 / 3 定义右移:
E1&gt;&gt;的值E2是E1右移E2位位置。如果E1有 无符号类型或E1具有带符号类型和非负值, 结果的值是E1商的不可分割的一部分 除以数量2提升到功率E2。 如果E1已签名 类型和负值,结果值是 实现定义强>
有关详细信息,请参阅此link。
答案 1 :(得分:1)
默认情况下,它是signed int。范围是-32767到32767,位位范围-111111111111111到+111111111111111左边的第一位充当负或正指示。并且所有算术运算都将以2的补码方法完成。通常,负int表示两个补码方法,即以-1为例表示-1。
4 Bytes = 32 bits
0000 0000 0000 0000 0000 0000 0000 0000
how represent 1
0000 0000 0000 0000 0000 0000 0000 0001
Then we invert the digits. 0 becomes 1, 1 becomes 0.
1111 1111 1111 1111 1111 1111 1111 1110
Then we add 1.
1111 1111 1111 1111 1111 1111 1111 1111
This is how -1 is represented
负数的右移定义为以1s移位到最高位位置,然后在2s补码表示中它将表现为算术移位 - 右移N的结果将与除以2N,向负无穷大四舍五入。所以-1的移位是-1 现在拿另一个号码 例如, 如果你有8位2s补码二进制数,则表示-3
0000 0011
Then we invert the digits.
1111 1100
Then we add 1.
1111 1101
11111101以十进制表示-3,并且您执行算术右移1,得到11111110,表示小数为-2,这与-3除以2 ^ 1相同,给出-1.5向负无穷大舍入在-2。
答案 2 :(得分:0)
在 Java 中,对于负数,>>
的行为定义明确(见下文)。
在 C ++ 中,对于负数,>>
的行为未定义(请参阅answer by rsp)。
引用Java语言规范,§15.19. Shift Operators:
n &gt;&gt; s 的值为 n 右移 s 位位置使用符号扩展。结果值为 floor(n / 2 s )。对于 n 的非负值,这相当于将整数除法(由整数除法运算符/计算)截断2,除以幂 s 。
n &gt;&gt;&gt; s 的值为 n 右移 s 位位置零扩展,其中:
如果 n 为正,则结果与 n&gt;&gt;的结果相同小号
如果 n 为负且左侧操作数的类型为
int
,则结果等于表达式(n&gt; &gt; s)+(2 <&lt;〜-s)。如果 n 为负且左侧操作数的类型为
long
,则结果等于表达式(n&gt; &gt; s)+(2L&lt;&lt; ~s)。