我没有学习IT,最近才遇到bit shifts和two's complement的申请。那么,您能否在解释中使用简单的英语,并假设我几乎不了解任何有关IP地址,位操作和Java数据类型的内容?
今天,我发现了以下一段代码(缩写):
long m = (-1) << (byte) 16;
现在,这是用于IP子网掩码。我知道我需要从4个8位块(即4个字节)开始,所有位都必须打开&#34;:11111111 11111111 1111111 1111111
接下来,零从右边移入,在这种情况下,16位&#39;价值;所以我们得到了11111111 11111111 00000000 0000000
面具。
但我确实有几个问题:
16
是否必须属于byte
类型才能实现此目的?long
。当上面的表达式运行时,-1
将被转换为 - 有效 - 4x8位块。 Java如何知道它需要32个位置/位(一个IP地址&#39;长度),而不是16或8,当应用两个补码时? (我猜这与long
数据类型有关吗?)-1
? (如果你问-0b1
二进制是什么,谷歌会给你-1
。我首先想到它可能与溢出有关,但它不是,是吗......?)< / LI>
更新: 16
在运行时由方法生成;我只是在这里放一个常数作为例子。事后看来可能是一个坏主意...
答案 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)。
否则,如果操作数是编译时类型byte,short或 char,通过扩展原语将其提升为int类型的值 转换(§5.1.2)。
因此byte
值扩展为int
。你的第一个问题没有。
表达式的结果是类型int
(32位)的值。它必须分配给long
(64位)变量,因此在分配之前该值将为widened to a long
。
整数类型是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位)。回答你的问题:
int
类型,但由于long
的类型需要它,因此转换为m
。-1
是编码的在两个补码中。您需要一些方式来表示除了位之外的其他数字。另外,这里有两个补码扮演副角色:它只是-1
被编码为全1位。long
,在左侧添加了32个1位。