我对这个愚蠢的结构有很多麻烦。我不明白为什么会这样做,我真的不确定如何解决它。我知道如何修复它的唯一方法是删除结构并以其他方式执行(我不想这样做)。
所以我正在读取文件中的数据,而我正在将它读入一个结构指针。看起来我的'long long'的偏移/指针每次都搞砸了。查看下面的详细信息。
所以这是我的结构:
struct Entry
{
unsigned short type;
unsigned long long identifier;
unsigned int offset_specifier, length;
};
这是我的代码,用于读取结构指针/数组中的所有废话:
Entry *entries = new Entry[SOME_DYNAMIC_AMOUNT];
fread(entries, sizeof(Entry), SOME_DYNAMIC_AMOUNT, openedFile);
如您所见,我将所有内容写入结构数组中。现在,我将向您展示我正在阅读的数据(对于此示例中的第一个结构)。
所以这是进入'entries'中第一个元素的数据。第一项(短,'类型')似乎很好。之后,当读取'标识符'时,似乎整个结构被移位了X个字节。这是第一个元素的图片(在反转结尾之后):
这是内存中的数据(红色方块是它开始的地方):
我知道这有点令人困惑,但我尽可能地解释它。感谢任何帮助,Hetelek。 :)
答案 0 :(得分:6)
使用额外的字节填充结构,以便更快地访问字段。您可以使用#pragma pack
阻止此操作:
#pragma pack(push, 1)
struct Entry
{
/* ... */
};
#pragma pack(pop)
请注意,这可能不是100%可移植的(我知道至少GCC和MSVC支持x86)。
答案 1 :(得分:3)
以二进制形式读取和写入结构文件是危险的。
您遇到的问题是编译器在结构的type
和identifier
成员之间插入填充(对齐所需)。显然,无论编写的程序,数据(你还没有告诉我们)都使用了一个不同的布局,即试图读取数据的程序。
如果两个系统(写入数据的系统和读取数据的系统)具有不同的对齐要求,因此Entry
类型的布局不同,就会发生这种情况。
但是,协调不是唯一的潜在问题; endianness中的差异也可能是一个严重的问题。对于预定义的整数类型,不同的系统可能具有不同的大小。您不能假设struct Entry
将具有一致的布局,除非处理它的所有代码都在单个系统上运行 - 并且理想情况下使用相同编译器的相同版本。
你可能能够使用#pragma pack
来解决这个问题,但我不建议这样做。它不可移植,it can be unsafe。充其量,它将解决成员之间填充的问题;从一个系统到另一个系统,布局仍然有很多种不同的方式。
如果不知道您正在阅读的文件的数据布局在何处以及如何定义,则无法为您提供明确的解决方案。
如果我们假设每条记录的文件布局是,例如:
type
)identifier
)offset_specifier, length
)然后你应该将数据读入unsigned char[]
缓冲区,或者读入uint16_t
,uint32_t
和uint64_t
类型的对象(在<cstdint>
中定义)或<stdint.h>
),然后将其从网络字节顺序转换为本地字节顺序。
您可以将此转换包装在从文件读取并转换数据的函数中,并将其存储在Entry
结构中。
如果您可以假设程序只能在一组受限制的系统上运行,那么您可以绕过其中的一部分。例如,您可以调整struct Entry
的声明,使其与文件格式匹配,并直接读取和写入。这样做意味着您的代码无法移植到某些系统。您必须决定愿意支付哪个价格。