Objective-C 如何将字节数组转换为 UInt64
How Convert Byte Array To UInt64 In Objective-C
到目前为止,这是我将收到的 8 个字节转换为 UInt64 所做的工作:
+ (UInt64)convertByteArrayToUInt64:(unsigned char *)bytes ofLength:(NSInteger)length
{
UInt64 data = 0;
for (int i = 0; i < length; i++)
{
data = data | ((UInt64) (bytes[i] & 0xff) << (24 - i * 8));
}
return data;
}
将数据转换为8字节数据的发送方是这样处理的:
for(int i=1;i<9;i++)
{
statusdata[i] = (time >> 8*i & 0xff);
}
我收到的8字节数据数据是:
01 00 00 00 00 00 00 3b
我的方法的输出是:
16777216
我尝试使用计算器将这个“16777216”转换为字节,我得到:
01 00 00 00 00 00 00
这意味着 3b 未包含在转换中。
但是,我在 java 下尝试了这段代码,它工作正常。我不知道问题出在哪里。
请帮忙。提前致谢!
A UInt64
是 8 个字节,所以如果你有一个 8 字节的缓冲区,你需要做的就是创建一个指向它的 UInt64
指针并取消引用它(只要数据在x86 架构上的 little-endian 格式,但我稍后会讲到),
所以:
unsigned char foo[8] = {0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01};
UInt64 *n = (UInt64 *) foo; // pointer to value 0x0102030405060708
UInt64 nValue = *n;
请注意,虽然 x86 硬件上的各个字节值是小端字节序的,因此缓冲区中的最低有效字节 首先 。因此,如果您将上面的缓冲区视为单独的 base-16 数字,则数字将为:
0x0102030405060708(最重要的字节在缓冲区的最后)。
不过,您正在寻找的技巧是简单地将 8 字节缓冲区转换为 UInt64*
并取消引用它。如果你在我推荐你去阅读它之前从未见过 big-vs.-little endian storage/byte-order。
p.s。 - 顺便说一句,发件人代码错误,数组索引 (i
) 需要 运行 从 0 到 7,所以 (i=0;i<8;++i)
、 不是 1- 8 或 time
的值将无法正确复制。顺便说一句,发送者 是 试图以小端顺序(缓冲区中的最低有效字节在前)将 time
复制到 statusdata
中,但同样,它正在做错了。
此外,如果发件人代码在 Java 上,您需要注意 time
的值实际上不应为负数。 Java 没有无符号整数值,因此如果 time
是负数并且您将其重构为 UInt64 它将是一个很大的正值,这不是您想要的。
为了完整起见,我将向您展示如何从小端缓冲区逐字节重构数据,但请记住,发送方代码是错误的,需要重写为从零开始索引(如上所示的类型转换也会让你到达那里):
data = 0
for (i=0; i < 8; ++i) {
data = (data << 8) | bytes[i]; // bytes is already UInt8 * so no need to mask it
}
到目前为止,这是我将收到的 8 个字节转换为 UInt64 所做的工作:
+ (UInt64)convertByteArrayToUInt64:(unsigned char *)bytes ofLength:(NSInteger)length
{
UInt64 data = 0;
for (int i = 0; i < length; i++)
{
data = data | ((UInt64) (bytes[i] & 0xff) << (24 - i * 8));
}
return data;
}
将数据转换为8字节数据的发送方是这样处理的:
for(int i=1;i<9;i++)
{
statusdata[i] = (time >> 8*i & 0xff);
}
我收到的8字节数据数据是:
01 00 00 00 00 00 00 3b
我的方法的输出是:
16777216
我尝试使用计算器将这个“16777216”转换为字节,我得到:
01 00 00 00 00 00 00
这意味着 3b 未包含在转换中。
但是,我在 java 下尝试了这段代码,它工作正常。我不知道问题出在哪里。
请帮忙。提前致谢!
A UInt64
是 8 个字节,所以如果你有一个 8 字节的缓冲区,你需要做的就是创建一个指向它的 UInt64
指针并取消引用它(只要数据在x86 架构上的 little-endian 格式,但我稍后会讲到),
所以:
unsigned char foo[8] = {0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01};
UInt64 *n = (UInt64 *) foo; // pointer to value 0x0102030405060708
UInt64 nValue = *n;
请注意,虽然 x86 硬件上的各个字节值是小端字节序的,因此缓冲区中的最低有效字节 首先 。因此,如果您将上面的缓冲区视为单独的 base-16 数字,则数字将为:
0x0102030405060708(最重要的字节在缓冲区的最后)。
不过,您正在寻找的技巧是简单地将 8 字节缓冲区转换为 UInt64*
并取消引用它。如果你在我推荐你去阅读它之前从未见过 big-vs.-little endian storage/byte-order。
p.s。 - 顺便说一句,发件人代码错误,数组索引 (i
) 需要 运行 从 0 到 7,所以 (i=0;i<8;++i)
、 不是 1- 8 或 time
的值将无法正确复制。顺便说一句,发送者 是 试图以小端顺序(缓冲区中的最低有效字节在前)将 time
复制到 statusdata
中,但同样,它正在做错了。
此外,如果发件人代码在 Java 上,您需要注意 time
的值实际上不应为负数。 Java 没有无符号整数值,因此如果 time
是负数并且您将其重构为 UInt64 它将是一个很大的正值,这不是您想要的。
为了完整起见,我将向您展示如何从小端缓冲区逐字节重构数据,但请记住,发送方代码是错误的,需要重写为从零开始索引(如上所示的类型转换也会让你到达那里):
data = 0
for (i=0; i < 8; ++i) {
data = (data << 8) | bytes[i]; // bytes is already UInt8 * so no need to mask it
}