Typecast结构到字节数组,以便稍后调用fwrite

时间:2014-02-04 20:35:13

标签: c memory layout structure

我的程序会经常将数据包写入磁盘(fwrite()),并通过以太网发送(send())。数据包按如下结构组织:

        struct PacketStruct{

              uint32_t Type;
              uint8_t * DataPtr;
              uint32_t Length;

        };

内存是动态分配的,指针分配给PacketStruct.DataPtr。

我的问题是,我想使用另一个结构来组织DataPtr最终指向的数据。例如:

        struct MyStruct{
              uint32_t A;
              uint8_t B;
              uint32_t C;
        };

然后:

        NewPacket = malloc( sizeof(struct PacketStruct) );
        NewStruct = malloc( sizeof(struct MyStruct) );
        NewStruct->A = 1;
        NewStruct->B = 2;
        NewStruct->C = 3;

如果我这样做:

        NewPacket->DataPtr = (uint8_t *) NewStruct;
        NewPacket->Length = sizeof( struct MyStruct);

当我这样做时,我是否会遇到结构填充等问题:

        fwrite( (void *) NewPacket->DataPtr, 1, (size_t) NewPacket->Length, fout); 

1 个答案:

答案 0 :(得分:0)

这取决于你对“问题”的意思。以下是我看到的潜在陷阱:

1)struct MyStruct可能包含任何成员之后的填充(可能会在B之后)。此填充所涵盖的内存不会由malloc或您的赋值语句初始化。如果您改为使用calloc,则这些区域将初始化为0。

2)如果你需要从文件中读回结构,它将在相同的实现中工作(成员的对齐是实现定义的)。但是一旦你更改了体系结构,编译器,甚至编译器选项,你就不会回读你所写的内容。

3)使用强制转换可以防止编译器进行任何可能捕获错误的类型检查。如果您可以控制struct PacketStruct的定义,请考虑使用union的{​​{1}}种可能类型。这允许您准确指定您期望的类型,在您关心字节时将数据视为DataPtr,将其视为一个时将其视为uint8_t

4)更多的挑剔,但是:你不需要调用struct MyStruct的演员表,如果这些字段的定义稍后改变,理论上可以隐藏错误。