我在NSData对象中有一些字节。
我想将前四个字节转换为无符号大端int。
接下来的2个成为无符号的大端短,接下来的4个成为无符号的大端长。
一般来说,我需要弄清楚如何将字符串分解为我期望的任何原始类型。
这是我从前4个字节获取int的最佳尝试:
int position = 0;
const unsigned char *firstFourBytes;
[stream getBytes:&firstFourBytes range:NSMakeRange(position , 4)];
uint32_t test = *(uint32_t*)firstFourBytes;
position+=4;
有谁能告诉我这样做的最佳方法?谢谢!
答案 0 :(得分:1)
您拥有的代码不正确:
int position = 0;
const unsigned char *firstFourBytes;
在您声明firstFourBytes
作为指针之上,您有不分配了一个可容纳4个字节的缓冲区,firstFourBytes
本身未初始化
[stream getBytes:&firstFourBytes range:NSMakeRange(position , 4)];
getBytes:range:
需要一个指向缓冲区的指针,它可以将字节复制到该缓冲区中。您传递&firstFourBytes
,它是指向用于变量firstFourBytes
的存储的指针,因此您要求将字节复制到firstFourBytes
所指向的缓冲区中,而不是{{1}本身。幸运的是,你只要求4个字节,firstFourBytes
是4个(32位软件)或8个(64位软件)字节,所以字节适合......
sizeof(unsigned char *)
但是你现在拿这四个字节,这是你的大端4字节整数,并使用它们(如果是64位,还有4个额外的垃圾字节)作为指向内存的指针,并尝试从中读取一个四字节整数随机位置。 可能工作并返回垃圾,它可能会崩溃。
uint32_t test = *(uint32_t*)firstFourBytes;
如何操作
你需要:
解决(1)和(2)的最简单方法是声明所需类型的变量 - 编译器将处理对齐,(Objective-)C允许您获取任何变量的地址并将其用作一个字节缓冲区。所以你从:
开始position+=4;
现在可以通过将其视为字节缓冲区来直接读取所需的字节数:
UInt32 uint32bytes;
注意:必须检查提供的范围是否在[stream getBytes:&uint32bytes
range:NSMakeRange(position, sizeof(UInt32))
];
之内,因为stream
如果不是getBytes:range:
将会引发异常。
现在你在uint32bytes
中有4个字节,但是它们是big-endian顺序,你的平台可能是little-endian(就像x86一样)。为了解决这个问题,Apple提供了Byte Order Utilities,这是一组函数,用于在字节序格式之间转换不同大小的数据。您正在寻找的函数是CFSwapInt32BigToHost
,它可以从big-endian转换为您的平台(主机)使用的任何东西 - 所以在大端平台上它什么都不做,在小端平台上它交换字节。所以你现在可以:
UInt32 result = CFSwapInt32BigToHost(uint32bytes);
你有结果。
您可以将此模板应用于其他类型,例如UInt16
,以及使用字节顺序实用程序中的相应功能。
HTH