我已经看到了有关结构的字节序的一些问题和答案,但它们与检测系统的字节序或在两个不同字节序之间转换数据有关。
但是,如果有一种方法可以强制执行给定结构的特定字节序,那么我现在想说的是。除了用很多在位域上操作的宏重写整个内容之外,还有一些好的编译器指令或其他简单的解决方案吗?
通用解决方案会很好,但是我也会对特定的gcc解决方案感到满意。
编辑:
感谢您的所有评论,指出为什么执行字节序不是一个好主意,但就我而言,这正是我所需要的。
特定处理器(永远不会改变,它是具有自定义硬件的嵌入式系统)生成大量数据,并且必须由运行在未知处理器上的程序(我正在研究)读取该数据。按字节计算数据非常麻烦,因为它由数百种不同类型的结构组成,这些结构巨大而又深:大多数结构内部都包含许多其他大型结构层。
更改嵌入式处理器的软件是不可能的。源可用,这就是为什么我打算使用该系统中的结构,而不是从头开始并按字节评估所有数据。
这就是为什么我需要告诉编译器应使用哪种字节序,无论效率如何与否无关紧要。
字节序不一定是实际更改。即使只是一个接口(interface),并且实际上所有事情都由处理器以其字节序进行处理,这对我来说是完全可以接受的。
最佳答案
我通常处理此问题的方式如下:
#include <arpa/inet.h> // for ntohs() etc.
#include <stdint.h>
class be_uint16_t {
public:
be_uint16_t() : be_val_(0) {
}
// Transparently cast from uint16_t
be_uint16_t(const uint16_t &val) : be_val_(htons(val)) {
}
// Transparently cast to uint16_t
operator uint16_t() const {
return ntohs(be_val_);
}
private:
uint16_t be_val_;
} __attribute__((packed));
对于
be_uint32_t
同样如此。然后,您可以像下面这样定义结构:
struct be_fixed64_t {
be_uint32_t int_part;
be_uint32_t frac_part;
} __attribute__((packed));
关键是编译器几乎肯定会按照您编写它们的顺序来排列字段,因此您真正担心的只是big-endian整数。
be_uint16_t
对象是一个类,该类知道如何根据需要在big-endian和machine-endian之间进行透明转换。像这样:be_uint16_t x = 12;
x = x + 1; // Yes, this actually works
write(fd, &x, sizeof(x)); // writes 13 to file in big-endian form
实际上,如果您使用任何相当不错的C++编译器来编译该代码段,则应该发现该代码段发出一个大端“13”作为常量。
对于这些对象,内存中的表示形式是big-endian。因此,您可以创建它们的数组,将它们放置在结构中,等等。但是当您对其进行操作时,它们神奇地转换为机器字节序。这通常是x86上的一条指令,因此非常有效。在某些情况下,您必须手动进行转换:
be_uint16_t x = 37;
printf("x == %u\n", (unsigned)x); // Fails to compile without the cast
...但是对于大多数代码,您只能像内置类型一样使用它们。
关于c++ - 有没有一种方法可以为C或C++结构强制执行特定的字节序?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6732127/