char* (Array) 强制转换为 unsigned long + 1?

char* (Array) cast to unsigned long + 1?

我正在尝试将一些 C 代码移植到 Java,但是我一直在努力弄清楚这些代码行的作用。

注意:rawEntrychar* 类型,似乎是 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

这个表达式

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();

在继续之前,重要的是要注意此代码取决于您平台上 long 的实际大小。在 64 位平台上 longs 是 64 位,即 long 占用 8 个字节。另一方面,ntohl 转换为 32 位长(4 字节)的“network long”。

假设rawEntry{1,0,0,0,0,0,0,0,0,0,0xB,0xDA,…}(0xB是以16为底相当于11,0xDA是以16为底(十六进制)unsigned对应于-38的值)

l = (unsigned long*) rawEntry + 1;

真正的意思是l指的是第二个unsigned long。即跳过 rawEntry 的前 8 个字节,然后 l 指向 {0,0,0xB,0xDA,…} 部分。现在 *l 是由 {0,0,0xB,0xDA,…} 字节序列表示的 unsigned long,它取决于您的体系结构。如果您使用的是 0x…DA0B0000 的小端计算机(省略号,因为数组的末尾是未知的,这是未定义的行为)。现在 ntohl 将只保留最后 32 位并反转字节顺序,导致 0x00000BDA 或基数 10 中的 3034。

在 Java 中写这个的简单方法是

offset = (rawEntry[8] << 24) +
         (rawEntry[9] << 16) +
         (rawEntry[10] << 8) +
         (rawEntry[11]);