3

我得到了一个来自 gzread 的调用的 cstring。我知道数据是块,每个块由一个无符号整数、字符、整数和无符号短整数组成。

所以我想知道将这个 cstring 拆分为适当变量的标准方法是什么。

说前 4 个字节,是 unsigned int,下一个字节是 char,接下来 4 个字节是有符号 int,最后 2 个字节是 unsigned short int。

//Some pseudocode below which would work
char buf[11];
unsigned int a;
char b;
int c;
unsigned short int d;

我想我可以用适当的偏移量来记忆。

memcpy(&a, buf, sizeof(unsigned int));
memcpy(&b, buf+4, sizeof(char));
memcpy(&c, buf+5, sizeof(int));
memcpy(&d, buf+9, sizeof(unsigned short int));

还是使用一些位运算符更好?比如移位和掩蔽。

或者将所有 11 个字节直接 gzreading 到某个结构中会更好,或者这甚至可能吗?结构的内存布局是否已修复,这是否适用于 gzread?

4

4 回答 4

2

如果您打包结构(阅读__packed__属性),您可以依赖顺序并且成员是不对齐的。因此,您可以直接读入结构。但是,我不确定此解决方案的可移植性。

否则,像这样使用指针魔法和强制转换:

char *buffer;
int a = *(reinterpret_cast<int*> (buffer))
unsigned short b = *(reinterpret_cast<unsigned short*> (buffer + sizeof(int)))
于 2011-10-11T05:48:51.813 回答
2

您需要确保文件的字节顺序与您运行代码的处理器架构相匹配。例如,如果整数首先以最高有效字节写入文件,并且您的处理器使用最低有效字节优先顺序,那么您将得到垃圾结果。

如果您想让您的代码从一种架构移植到另一种架构,您应该将整数的所有读写操作封装在宏或内联函数之后,根据目标处理器架构为您管理字节顺序。

于 2011-10-11T05:57:25.083 回答
1

这取决于如何定义输入数据。如果它被定义为主机端顺序(即,字节顺序始终与运行代码的系统相匹配),那么memcpy()您所展示的就是一种很好的可移植方法。

或者,如果输入数据被定义为具有特定的字节顺序,那么最好的可移植解决方案是一次加载一个unsigned char,使用移位和按位或。

于 2011-10-11T06:34:24.693 回答
1

在您做任何事情之前,您需要一个格式规范。它是文本还是二进制(可能是您的描述中的二进制,但永远不知道)?有符号值的表示形式是什么?什么是字节顺序? memcpy只有当你的机器架构与输入格式完全对应时才会起作用——今天这种情况很少见,因为几乎所有的网络格式都是大端的,而最普遍的架构是小端的。(今天的大多数格式和体系结构都使用 2 的补码来表示负值,因此您通常可以在那里“假设”兼容性。但也有例外。)

鉴于此,值的数学重建(使用掩码和移位或乘法)是唯一可移植的解决方案。根据机器和编译器的质量,它也很容易带来更好的性能。

于 2011-10-11T07:51:03.020 回答