位操作Java的位移位操作符是如何工作的?
我没有研究它,直到最近才发现bit shifts和two's complement的申请。那么,你能不能用简单的英语解释一下,假设我对IP地址、位操作和Java数据类型几乎一无所知
今天,我发现了以下代码(缩写):
long m = (-1) << (byte) 16;
现在,这是IP子网屏蔽。我知道我需要从4块8位(即4字节)开始,所有位都必须“打开”:11111111 11111111 1111111 1111111
接下来,零从右边移入,在这种情况下,值为16位;所以我们得到了11111111 11111111 00000000 0000000
,面具
但我确实有几个问题:
16
必须是byte
类型才能工作吗李>- 结果是类型
long
。当上面的表达式运行时,-1
被转换成有效的4x8bit块。当应用两个补码时,Java如何知道它需要32个位置/位(IP地址的长度),而不是16或8?(我猜这与long
数据类型有关?)李> - 为什么二的补语从一开始就适用于
-1
?(如果你问-0b1
什么是二进制的,谷歌会给你-1
。我起初以为这可能与溢出有关,但事实并非如此,是不是……?)李> - 真的,编译器在运行代码时会将其转换为什么数据类型,以使其正常工作李>
更新:在运行时通过一个方法生成16
;我只是把一个常数放在这里作为例子。事后看来可能是个坏主意
# 1 楼答案
实际上,您的
m
变量是long
类型是令人困惑的,因为IP地址是32位的,并且对应于int
。你的右手边确实是int
,只有在完全计算之后,它才扩展到long
(64位)。回答您的问题:int
类型,但会被转换为long
,因为m
类型需要它李>-1
在二的补码中被编码。你需要一些的方法来表示负数,除了位什么都没有。另外,二的补码在这里起到了一个副作用:它大约是-1
被编码为所有1位李>long
,在左侧再添加32个1位李># 2 楼答案
这个
是一个constant expression。它的值在编译时已知。它是一个
long
,值为-65536
(十进制表示)如果表达式不是常量表达式,则在计算表达式时变量的类型无关紧要。只有在以后将其值指定给变量时,它才有意义
比如说
上面的表达式包含一个移位运算符和两个操作数,一个是
int
类型,另一个是byte
类型The JLS states the following concerning shift operators and their operands
which is
因此
byte
值被扩大到int
。所以你的第一个问题是否定的表达式的结果将是}
int
(32位)类型的值。它必须被分配给一个long
(64位)变量,因此在分配之前,该值应该是widened to a ^{来自JLS again
这就是它们的存储方式