有没有一种方法可以对C或C ++结构强制执行特定的字节序? [英] Is there a way to enforce specific endianness for a C or C++ struct?

查看:146
本文介绍了有没有一种方法可以对C或C ++结构强制执行特定的字节序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经看到了有关结构的字节序的一些问题和答案,但是它们是关于检测系统的字节序或在两个不同字节序之间转换数据。

I've seen a few questions and answers regarding to the endianness of structs, but they were about detecting the endianness of a system, or converting data between the two different endianness.

但是,如果要强制执行给定结构的特定字节序,我现在想要的是。除了用很多在位域上操作的宏重写整个内容之外,还有一些好的编译器指令或其他简单的解决方案吗?

What I would like to now, however, if there is a way to enforce specific endianness of a given struct. Are there some good compiler directives or other simple solutions besides rewriting the whole thing out of a lot of macros manipulating on bitfields?

一般的解决方案会很好,但是我会

A general solution would be nice, but I would be happy with a specific gcc solution as well.

编辑:

谢谢。您需要提供所有注释,指出为什么执行字节序不是一个好主意,但就我而言,这正是我所需要的。

Thank you for all the comments pointing out why it's not a good idea to enforce endianness, but in my case that's exactly what I need.

一个特定的处理器(永远不会改变,它是具有自定义硬件的嵌入式系统),并且必须由运行在未知处理器上的程序(我正在研究)读取。按字节计算数据非常麻烦,因为它由数百种不同类型的结构组成,这些结构巨大而又深:大多数结构内部都有许多其他大型结构层。

A large amount of data is generated by a specific processor (which will never ever change, it's an embedded system with a custom hardware), and it has to be read by a program (which I am working on) running on an unknown processor. Byte-wise evaluation of the data would be horribly troublesome because it consists of hundreds of different types of structs, which are huge, and deep: most of them have many layers of other huge structs inside.

更改嵌入式处理器的软件是不可能的。源可用,这就是为什么我打算使用该系统中的结构,而不是从头开始并按字节评估所有数据。

Changing the software for the embedded processor is out of the question. The source is available, this is why I intend to use the structs from that system instead of starting from scratch and evaluating all the data byte-wise.

这就是为什么我需要告诉编译器应该使用哪种字节序,无论效率如何与否无关。

它没有成为字节序的真实更改。即使只是接口,并且实际上所有内容都由处理器以其字节序进行处理,这对我来说是完全可以接受的。

It does not have to be a real change in endianness. Even if it's just an interface, and physically everything is handled in the processors own endianness, it's perfectly acceptable to me.

推荐答案

我通常处理这种情况的方式是这样的:

The way I usually handle this is like so:

#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

然后您可以这样定义结构:

Then you can define your struct like this:

struct be_fixed64_t {
    be_uint32_t int_part;
    be_uint32_t frac_part;
} __attribute__((packed));

要点是,编译器几乎可以肯定会按照您编写它们的顺序排列字段,因此您真正担心的只是大端整数。 be_uint16_t 对象是一个类,该类知道如何根据需要在big-endian和machine-endian之间进行透明转换。像这样:

The point is that the compiler will almost certainly lay out the fields in the order you write them, so all you are really worried about is big-endian integers. The be_uint16_t object is a class that knows how to convert itself transparently between big-endian and machine-endian as required. Like this:

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作为常量。

In fact, if you compile that snippet with any reasonably good C++ compiler, you should find it emits a big-endian "13" as a constant.

有了这些对象,内存中的表示形式就是大尾数。因此,您可以创建它们的数组,将它们放置在结构中,等等。但是,当您对其进行操作时,它们神奇地转换为机器字节序。这通常是x86上的一条指令,因此非常有效。在某些情况下,您必须手动进行投射:

With these objects, the in-memory representation is big-endian. So you can create arrays of them, put them in structures, etc. But when you go to operate on them, they magically cast to machine-endian. This is typically a single instruction on x86, so it is very efficient. There are a few contexts where you have to cast by hand:

be_uint16_t x = 37;
printf("x == %u\n", (unsigned)x); // Fails to compile without the cast

无法编译...但是对于大多数代码,您只能使用它们就像它们是内置类型一样。

...but for most code, you can just use them as if they were built-in types.

这篇关于有没有一种方法可以对C或C ++结构强制执行特定的字节序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆