char* (Array) 强制转换为 unsigned long + 1?
char* (Array) cast to unsigned long + 1?
我正在尝试将一些 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
这个表达式
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]);
我正在尝试将一些 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,如果我翻转字节序
这个表达式
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]);