Java的位移操作员如何在幕后工作?

时间:2015-09-08 15:31:46

标签: java bit-manipulation bit twos-complement domain-masking

我没有学习IT,最近才遇到bit shiftstwo's complement的申请。那么,您能否在解释中使用简单的英语,并假设我几乎不了解任何有关IP地址,位操作和Java数据类型的内容?

今天,我发现了以下一段代码(缩写):

long m = (-1) << (byte) 16;

现在,这是用于IP子网掩码。我知道我需要从4个8位块(即4个字节)开始,所有位都必须打开&#34;:11111111 11111111 1111111 1111111接下来,零从右边移入,在这种情况下,16位&#39;价值;所以我们得到了11111111 11111111 00000000 0000000面具。

但我确实有几个问题:

  1. 16是否必须属于byte类型才能实现此目的?
  2. 结果类型为long。当上面的表达式运行时,-1将被转换为 - 有效 - 4x8位块。 Java如何知道它需要32个位置/位(一个IP地址&#39;长度),而不是16或8,当应用两个补码时? (我猜这与long数据类型有关吗?)
  3. 为什么要将{2}补码应用于-1? (如果你问-0b1二进制是什么,谷歌会给你-1。我首先想到它可能与溢出有关,但它不是,是吗......?)< / LI>
  4. 真的,编译器在运行代码时将其转换为什么数据类型,以使其全部工作?
  5. 更新: 16在运行时由方法生成;我只是在这里放一个常数作为例子。事后看来可能是一个坏主意...

2 个答案:

答案 0 :(得分:6)

  

真的,编译器将其转换为什么数据类型   运行代码,使其全部工作?

这个

(-1) << (byte) 16;

constant expression。它的值在编译时是已知的。它是long,其值为-65536(十进制表示)。

如果表达式不是常量表达式,则在计算表达式时,变量的类型无关紧要。只有将其值分配给变量才会有效。

以示例为例

int i = -1;
long m = i << (byte) 16;

上面的表达式涉及一个移位运算符和两个操作数,一个类型为int,另一个类型为byte

The JLS states the following concerning shift operators and their operands

  

对每个操作数分别执行一元数字提升(§5.6.1)。

which is

  

否则,如果操作数是编译时类型byte,short或   char,通过扩展原语将其提升为int类型的值   转换(§5.1.2)。

因此byte值扩展为int。你的第一个问题没有。

表达式的结果是类型int(32位)的值。它必须分配给long(64位)变量,因此在分配之前该值将为widened to a long

来自JLS again

  

整数类型是byte,short,int和long,其值   8位,16位,32位和64位带符号二进制补码整数,   分别为char和char,其值为16位无符号整数   代表UTF-16代码单元(§3.1)。

这就是它们的存储方式。

答案 1 :(得分:2)

实际上您的m变量属于long类型令人困惑,因为IP地址是32位且对应于int。您的右侧确实是int,并且只有在完全计算后它才会扩展到long(64位)。回答你的问题:

  1. 它没有。你可以删除演员阵容。
  2. 结果实际上是int类型,但由于long的类型需要它,因此转换为m
  3. 没有&#34;应用&#34;&#34;什么,真的。数字-1编码的在两个补码中。您需要一些方式来表示除了位之外的其他数字。另外,这里有两个补码扮演副角色:它只是-1被编码为全1位。
  4. 所有只是一个32位的一位被移到左边的一块,零填充空位。然后,为了转换为long,在左侧添加了32个1位。