【发布时间】:2020-07-24 08:29:27
【问题描述】:
我将文件的大部分内容作为“blob”数据读入char 数组。
我知道这些 blob 的结构,并为不同的结构创建了类。
然后我想将读取的char 数组转换为适当类对象的数组。
这在某些情况下效果很好,但我遇到了类成员的对齐/填充是一个问题的情况。
这是一个最小的示例,但我不是从文件中获取数据,而是在data_i1、data_d1 和data_i2 中定义数据,然后将其转换为c_data。
c_data代表从文件中读取的数据,包含data_i1、data_d1和data_i2两次。
如果没有对齐问题,如果我将c_data 转换为Data 的数组,我应该得到Data[0] 和Data[1] 中的初始数据。
#include <iostream>
class Data {
public:
int i1[2];
double d1[3];
int i2[3];
};
int main()
{
//Setting some data for the example:
int data_i1[2] = { 1, 100}; //2 * 4 = 8 bytes
double data_d1[3] = {0.1, 100.2, 200.3 }; //3 * 8 = 24 bytes
int data_i2[3] = { 2, 200, 305 }; //3 * 4 = 12 bytes
//total = 44 bytes
//As arrays the data is 44 bytes, but size of Data is 48 bytes:
printf("sizeof(data_i1) = %d\n", sizeof(data_i1));
printf("sizeof(data_d1) = %d\n", sizeof(data_d1));
printf("sizeof(data_i2) = %d\n", sizeof(data_i1));
printf("total size = %d\n\n", sizeof(data_i1) + sizeof(data_d1) + sizeof(data_i2));
printf("sizeof(Data) = %d\n", sizeof(Data));
//This can hold the above that of 44 bytes, twice:
char c_data[88];
//Copying the data from the arrays to a char array
//In reality the data is read from a binary file to the char array
memcpy(c_data + 0, data_i1, 8);
memcpy(c_data + 8, data_d1, 24);
memcpy(c_data + 32, data_i2, 12); //c_data contains data_i1, data_d1, data_i2
memcpy(c_data + 44, c_data, 44); //c_data contains data_i1, data_d1, data_i2 repeated twice
//Casting the char array to a Data array:
Data* data = (Data*)c_data;
//The first Data object in the Data array gets the correct values:
Data data1 = data[0];
//The second Data object gets bad data:
Data data2 = data[1];
printf("data1 : [%4d, %4d] [%4.1f, %4.1f, %4.1f] [%4d, %4d, %4d]\n", data1.i1[0], data1.i1[1], data1.d1[0], data1.d1[1], data1.d1[2], data1.i2[0], data1.i2[1], data1.i2[2]);
printf("data2 : [%4d, %4d] [%4.1f, %4.1f, %4.1f] [%4d, %4d, %4d]\n", data2.i1[0], data2.i1[1], data2.d1[0], data2.d1[1], data2.d1[2], data2.i2[0], data2.i2[1], data2.i2[2]);
return 0;
}
代码输出为:
sizeof(data_i1) = 8
sizeof(data_d1) = 24
sizeof(data_i2) = 8
total size = 44
sizeof(Data) = 48
data1 : [ 1, 100] [ 0.1, 100.2, 200.3] [ 2, 200, 305]
data2 : [ 100, -1717986918] [-92559653364574087271962722384372548731666605007261414794985472.0, -0.0, 0.0] [-390597128, 100, -858993460]
我应该如何正确处理这个问题? 我可以以某种方式禁用此填充/对齐(如果这是正确的术语)?是否可以为该类创建一个成员函数来指定如何进行转换?
【问题讨论】:
-
查看数据的对齐方式。
-
@Jarod42 那个重复的帖子有一些有用的信息,但它不是重复的。我不是在问为什么尺寸不同,或者对齐方式是什么。我在问,鉴于在这种情况下对齐是一个问题,我应该如何处理这个问题。
-
您似乎在寻找
__attribute__((packed))或pragma pack。 -
只是不要将字节转换为其他类型,甚至不要转换为 POD 结构。 C++ 不保证它会工作。定义一个实际的
Data[2]并以通常的方式命名其成员,例如Data[0].i1[0]。 -
您的
c_data数组中有 48 个字节,但您复制 88 并尝试读取 96。这会导致未定义的行为。data[1]将从这个越界数据中读取。
标签: c++ class padding memory-alignment