我正在尝试将一些C代码移植到Java,但是我一直在努力弄清楚这些代码行的作用。
注意:rawEntry
的类型为char*
,并且看起来是12字节长,因此
char *rawEntry = (char*)malloc(0x000c);
unsigned long *l;
unsigned long offset;
// ...
l = (unsigned long*) rawEntry + 1;
offset = ntohl(*l);
据我所知,它需要数组的前四项,并将它们组合在一起构成一个long,但是我在java中的尝试并不成功。
offset = (rawEntry[0] << 24) +
(rawEntry[1] << 16) +
(rawEntry[2] << 8) +
(rawEntry[3]) +
1;
当出现以下数组时,
1 0 0 0 0 0 0 0 0 0 11 -38
C代码输出3034作为偏移量
我的Java代码输出16777217,如果我翻转字节序,则输出1
答案 0 :(得分:5)
此表达式
l = (unsigned long*) rawEntry + 1;
将rawEntry
转换为指向系统上大小为8字节的类型的指针。之后,添加1
意味着添加8个字节,因此实际转换如下所示:
offset = (Byte.toUnsignedInt(rawEntry[ 8]) << 24) +
(Byte.toUnsignedInt(rawEntry[ 9]) << 16) +
(Byte.toUnsignedInt(rawEntry[10]) << 8) +
(Byte.toUnsignedInt(rawEntry[11]) << 0);
以下四个字节被解释为3034
:
0 0 11 -38
您应该可以使用ByteBuffer
:
int offset = ByteBuffer.wrap(rawEntry, 8, 4).getInt();
答案 1 :(得分:2)
在进一步说明之前,请务必注意此代码取决于平台上long
的实际大小。在64位平台上,long是64位,即long
占用8个字节。另一方面,ntohl
转换为32位长(4字节)的“网络长”。
假设rawEntry
是{1,0,0,0,0,0,0,0,0,0,0xB,0xDA,…}
(0xB是11的基数16,0xDA是对应于-38的基数16(十六进制)unsigned
值
l = (unsigned long*) rawEntry + 1;
实际上意味着l
指的是第二个unsigned long
。这是从rawEntry
和l
跳过前8个字节,然后指向{0,0,0xB,0xDA,…}
部分。现在*l
是unsigned long
字节序列所代表的{0,0,0xB,0xDA,…}
,它取决于您的架构。如果你在一个小的endian机器上将是0x ... DA0B0000(省略号,因为数组的末尾是未知的,这是未定义的行为)。现在ntohl
将保留最后的32位并反转字节顺序,从而产生0x00000BDA或基数10中的3034.
用Java编写它的简单方法是
offset = (rawEntry[8] << 24) +
(rawEntry[9] << 16) +
(rawEntry[10] << 8) +
(rawEntry[11]);