在C++中更改整个结构的字节序
Change endianness of entire struct in C++
我正在用C++编写一个解析器来解析一个定义良好的二进制文件。我已经声明了所有必需的结构。而且由于我只对特定字段感兴趣,因此在我的结构中,我通过创建大小等于跳过的字节的 char 数组来跳过非必需字段。所以我只是读取 char 数组中的文件并将 char 指针强制转换为我的结构指针。现在的问题是该二进制文件中的所有数据字段都是大端序,因此在类型转换之后,我需要更改所有结构字段的字节序。一种方法是为每个字段手动执行此操作。但是有很多字段的各种结构,所以手动操作会非常麻烦。那么实现这一目标的最佳方法是什么。而且由于我将解析非常大的此类文件(例如TB的文件(,因此我需要一种快速的方法来执行此操作。
编辑:我有使用属性(打包(,所以无需担心填充。
如果你可以进行未对齐的访问而不会受到惩罚,并且你不介意编译器或平台特定的技巧来控制填充,这是可以工作的。(我假设你对此没问题,因为你提到了__attribute__((packed))
(。
在这种情况下,最好的方法是为原始数据类型编写值包装器,并在首先声明结构时使用这些包装器而不是原始类型。请记住,值包装器必须是琐碎的/类似 POD 的才能正常工作。如果你有一个POSIX平台,你可以使用ntohs/ntohl
进行字节序转换,那么无论你自己写什么,它都可能得到更好的优化。
如果平台上未对齐的访问是非法的或速度较慢,则需要改为反序列化。由于我们还没有反射,您可以使用相同的值包装器(加上一个Ignore<N>
占位符,跳过您不感兴趣的字段的 N 个字节(来执行此操作,并在元组而不是结构中声明它们 - 您可以迭代元组中的成员并告诉每个成员从消息中反序列化自己。
一种方法是将 C 预处理器与C++运算符结合使用。像这样编写几个C++类:
#include "immintrin.h"
class FlippedInt32
{
int value;
public:
inline operator int() const
{
return _bswap( value );
}
};
class FlippedInt64
{
__int64 value;
public:
inline operator __int64() const
{
return _bswap64( value );
}
};
然后
#define int FlippedInt32
在包含定义这些结构的标头之前。#undef
#include
后立即
.这将用FlippedInt32
替换结构中的所有int
字段,它具有相同的大小,但返回翻转的字节。
如果它是您自己的结构,您可以修改,则不需要预处理器部分。只需将整数替换为字节翻转类即可。
如果你能列出需要字节序转换的字段的偏移量(以字节为单位,相对于文件顶部(,以及这些字段的大小,那么你可以直接在 char 数组上使用单个 for 循环进行所有字节序转换。 例如,像这样的东西(伪代码(:
struct EndianRecord {
size_t offsetFromTop;
size_t fieldSizeInByes;
};
std::vector<EndianRecord> todoList;
// [populate the todo list here...]
char * rawData = [pointer to the raw data]
for (size_t i=0; i<todoList.size(); i++)
{
const EndianRecord & er = todoList[i];
ByteSwap(&rawData[er.offsetFromTop], er.fieldSizeBytes);
}
struct MyPackedStruct * data = (struct MyPackedStruct *) rawData;
// Now you can just read the member variables
// as usual because you know they are already
// in the correct endian-format.
。当然,困难的部分是想出正确的todoList
,但由于文件格式是明确定义的,因此应该可以通过算法生成它(或者更好的是,使用例如可以调用的GetNextEndianRecord()
方法将其创建为生成器,这样您就不必在内存中存储非常大的向量(
- struct.error:解压缩 C++ 结构时,解包需要 288 字节的缓冲区
- DNS 查询格式标头结构中的小字节序问题
- 哪些值存储在对齐的结构/类对象的填充字节中
- 为什么这个结构需要 24 个字节
- 正在转换结构数据的字节序
- 在C++中更改整个结构的字节序
- 使用字节数组具有单字节对齐方式的结构是否安全
- 在字节数组上转换具有虚函数的结构是否安全?
- 为什么标准库不以无锁的方式为 8 字节以下的结构实现 std::atomic?
- 将结构中的字节数组传递给 com 对象
- 为什么在未由语言本身定义的结构字节中的位字段顺序
- C 将5个字节结构与Cacheline保持一致
- C++结构到字节*引发错误
- 填充C 中C结构的填充字节?(不关心结构包装!)
- 将结构添加到字节向量,然后添加另一个
- uint12 结构中的字节序
- C 在结构中添加所有字节
- 具有3字节块的序列化C 结构
- 使用指针访问结构的各个字节
- 将字符串转换为结构(字节)