移位时字节值的内存分配

时间:2014-08-23 19:44:34

标签: java memory-management binary

我为自己编写了一个小型演示,以便更好地理解移位字节值。所以我的字节'd'的值为127:

class Demo {
    public static void main (String args[]) {

        byte d = 127; // 8-bit is equal to 0 111 1111

我尝试做的是将值向左移动到左边:

int e = d << 2; /* 32-bit shifted value is equal to 0 000 0000 0000 0000 0000 0001 1111 1100
    0 * 2^0 + 0 * 2^1 + 1 * 2^2 + 1 * 2^3 + 1 * 2^4 + 1 * 2^5 + 1 * 2^6 + 1 * 2^7 + 1 * 2^8 = 
    0 * 1   + 0 * 2   + 1 * 4   + 1 * 8   + 1 * 16  + 1 * 32  + 1 * 64  + 1 * 128 + 1 * 256 = 
    0       + 0       + 4       + 8       + 16      + 32      + 64      + 128     + 256     = 508
*/

如果我的评论中的逻辑是正确的,请告诉我,因为这是我第一次做这样的事情。所以真正的问题是关于内存分配,一旦我尝试将'e'转换回byte:

byte f = (byte)(e); /* [] indicates 8-bit at 32-bit shifted value: 0 000 0000 0000 0000 0000 0001 [1111 1100]
    0 * 2^0 + 0 * 2^1 + 1 * 2^2 + 1 * 2^3 + 1 * 2^4 + 1 * 2^5 + 1 * 2^6 - 1 * 2^7 = 
    0 * 1   + 0 * 2   + 1 * 4   + 1 * 8   + 1 * 16  + 1 * 32  + 1 * 64  - 1 * 128 = 
    0       + 0       + 4       + 8       + 16      + 32      + 64      - 128     = -4
*/

int g = (byte)(e);

    }
}

字节'f'和int'g'都很完美,但我现在正在阅读的书建议我使用类似条件的int而不做任何解释,所以我担心的真实事情是'内存分配'。使用哪种类型或者一旦字节值移位并且内存扩展到32位是否真的重要,是不是可以将其减少到8位?

另外,我有一个奇怪的问题。如何查看任何值的真实“位数”?让我们说当我执行这样的事情时:

byte a = 10;
System.out.println(Integer.toBinaryString(a));
int b = 10;
System.out.println(Integer.toBinaryString(b));

两种情况下结果都是'1010'。但是,如果我得到正确的字节'a'使用8位内存而int'b'使用32.但是对于:

byte c = 5 << 1;
System.out.println(Integer.toBinaryString(c));

结果也是'10​​10',但现在它使用32位内存,而在计算表达式时,字节和短值被提升为int。我怎样才能真实地看到这一点并由我自己确保?

1 个答案:

答案 0 :(得分:1)

我不完全确定您要执行的操作,但对于fg的分配,两者都会给出相同的结果,因为您为其分配了(byte) e它适合一个字节变量。

如果你在没有强制转换的情况下进行分配,你会得到不同的结果,因为e的值太大而不适合一个字节。

对于toBinaryString的结果,它们显然不显示前导零,这就是为什么你看到一个字节变量和一个保持相同值的int变量的相同结果。如果你想看到所有的位,你必须自己打印前导零,前导零的数量取决于变量的类型(因此,对于一个字节变量,你必须添加前导零到总共达到8位,对于int,你必须达到32位等等。)。

如果您想查看前导零,可以创建自己的toBinaryString版本。查看Integer的实施,我发现toBinaryString调用toUnsignedString

 public static String toBinaryString(int i) {
     return toUnsignedString(i, 1);
 }

 private static String toUnsignedString(int i, int shift) {
     char[] buf = new char[32];
     int charPos = 32;
     int radix = 1 << shift;
     int mask = radix - 1;
     do {
         buf[--charPos] = digits[i & mask];
         i >>>= shift;
     } while (i != 0);
     return new String(buf, charPos, (32 - charPos));
 }

如您所见,此方法仅返回表示int的二进制值的32 char的一部分。如果您返回new String(buf),您将获得带有前导零的完整二进制字符串。