为什么我无法在 Java 中屏蔽长数据类型的 32 位

Why am I not able to mask 32 bits on a long data type in Java

我不明白为什么会这样。我试图在 long 上屏蔽 java 的最低有效 32 位,但它没有正确地屏蔽第 33 位和第 34 位以及更远的位。这是我的例子

class Main {
  public static void main(String[] args) {
    long someVal = 17592096894893l; //hex  0xFFFFAAFAFAD
    long mask = 0xFF; //binary
    long result = mask & someVal;                  

    System.out.println("Example 1 this works on one byte");
    System.out.printf("\n%x %s", someVal, Long.toBinaryString(someVal) );
    System.out.printf("\n%x %s", result, Long.toBinaryString(result) );

    long someVal2 = 17592096894893l; //hex  0xFFFFAAFAFAD
    mask = 0xFFFFFFFF; //binary
    result = mask & someVal2; 
    System.out.println("\nExample 2 - this does not work");
    System.out.printf("\n%x %s", someVal2, Long.toBinaryString(someVal2) );
    System.out.printf("\n%x %s", result, Long.toBinaryString(result) );
  }
}

我原以为结果会将最高有效字节丢弃为零,因为 AND 运算是在 32 位上进行的。这是我得到的输出。

Example 1 - this works
ffffaafafad 11111111111111111010101011111010111110101101
ad 10101101
Example 2 - this does not work

ffffaafafad 11111111111111111010101011111010111110101101
ffffaafafad 11111111111111111010101011111010111110101101

我希望能够屏蔽 long 值的前 4 个最低有效字节。

我相信您在这里看到的是 Java 使用符号扩展将整数转换为长整数。

对于初学者,这段代码应该做什么?

int myInt = -1;
long myLong = myInt;
System.out.println(myLong);

这应该直观地打印出 -1,这确实发生了。我的意思是,如果在将 int 转换为 long 时,我们没有得到与开始时相同的数字,那就有点奇怪了。

现在,我们来看这段代码:

int myInt = 0xFFFFFFFF;
long myLong = myInt;
System.out.println(myLong);

这打印了什么?嗯,0xFFFFFFFF 是带符号的 32 位数字 -1 的十六进制版本。这意味着这段代码完全等同于上面的代码,所以它应该(并且确实)打印相同的值 -1.

但是编码为 long 的值 -1 没有表示 0x00000000FFFFFFFF。那将是 232 - 1,而不是 -1。相反,由于它是 64 位长,-1 表示为 0xFFFFFFFFFFFFFFFFFF。哎呀——所有的高位都被激活了!这使得它作为位掩码不是很有效。

Java中的规则是,如果将 int 转换为 long,如果 int 的第一位为 1,则 long 的所有 32 个高位也将设置为 1 .这样就可以将整数转换为长整数,从而保留数值。

如果你想制作一个实际上是 64 位长的位掩码,请使用 long 文字而不是 int 文字对其进行初始化:

mask = 0xFFFFFFFFL; // note the L

为什么这会有所不同?没有 L,Java 将代码视为

  1. 创建整数值 0xFFFFFFFF = -1,给 32 一个位。
  2. 将该整数值转换为长整型。为此,使用符号扩展将其转换为长值 -1,连续给出 64 个一位。

但是,如果包含 L,Java 会解释如下:

  1. 创建 long 值 0xFFFFFFFF = 232 - 1,即 32 个零位后跟 32 个一位。
  2. 将该值分配给掩码。

希望对您有所帮助!