我必须在道具上工作。二进制文件格式,并希望通过使用结构来实现它
我需要在我的结构中使用恒定的字节序列,并且我不知道如何实现它。
我想到了类似的东西:
#include <cstdint>
#pragma pack(push,1)
typedef struct PAYLOAD_INFO {
const uint8_t magicnumber[4] = { 0xFA, 0x11 , 0x28 , 0x33 };
uint16_t UMID;
const uint16_t VID = 1487 ;
uint32_t crc;
};
#pragma pack(pop)
int main (){
PAYLOAD_INFO pldInst;
pldInst.UMID = 5;
pldInst.crc = 0x34235a54;
...
writeToFile(&PAYLOAD_INFO,sizeof(PAYLOAD_INFO));
}
最后,“pldInst”应该看起来像那样(在内存中),而不考虑本例中的byteorder:
0x00000000: 0xFA, 0x11 , 0x28 , 0x33
0x00000004: 0x00, 0x05 , 0x05 , 0xCF
0x00000008: 0x34, 0x23 , 0x5a , 0x54
我已经尝试过“默认”方法:
#include <cstdint>
#pragma pack(push,1)
typedef struct PAYLOAD_INFO {
static const uint8_t magicnumber[4];
uint16_t UMID;
static const uint16_t VID = 1487 ;
uint32_t crc;
};
const uint8_t magicnumber[4] = { 0xFA, 0x11 , 0x28 , 0x33 };
#pragma pack(pop)
但不能按预期工作。
有没有办法在不计算每个struct成员的内存大小,分配新内存和复制每个成员的情况下完成这项工作?
我使用g ++ 4.6.3。
方面, 托马斯
更新:
@bikeshedder提供的c ++ 11解决方案效果很好,但只能用g ++ 4.7或更高版本编译。
答案 0 :(得分:4)
您的静态目前只是定义全局静态。您需要添加一个类说明符来定义要成为类的一部分的静态。
const uint8_t PAYLOAD_INFO::magicnumber[4] = { 0xFA, 0x11 , 0x28 , 0x33 };
也就是说,正如@bikeshedder在下面提到的那样,静态分别存储在内存中,所以当你创建一个新的struct实例时,该实例不会在实例的内存位置中包含幻数,所以你使用{{ 1}}将无法按预期工作。
答案 1 :(得分:3)
我建议不要将任何类型的structs
转换为原始内存,除非你使用的是一些内核接口,它保证在同一台机器上运行并且应该以这种方式使用。
这不是可移植的(字节序问题),每个编译器都有一点不同,性能确实不是那么好。总而言之,这并不能成为这种不良行为的理由。
您的代码示例不起作用的原因是静态成员。由于静态成员不是对象(但是类)的一部分,因此只有UMID
和crc
被写入。
struct PAYLOAD_INFO {
const uint8_t magicnumber[4] = { 0xFA, 0x11, 0x28, 0x33 };
uint16_t UMID;
const uint16_t VID = 1487 ;
uint32_t crc;
};
此代码仅适用于C ++ 11,但由于您包含cstdint
,我假设您已使用该C ++版本。如果不使用C ++ 11,则需要在构造函数中初始化成员,并且不能使用const
作为幻数,因为它无法初始化。 (见:initialize a const array in a class initializer in C++)
struct PAYLOAD_INFO {
const uint8_t magicnumber[4] = { 0xFA, 0x11, 0x28, 0x33 };
uint16_t UMID;
const uint16_t VID = 1487 ;
uint32_t crc;
};
对于C ++ 98,您需要执行以下操作:
struct PAYLOAD_INFO {
uint8_t magicnumber[4];
uint16_t UMID;
const uint16_t VID;
uint32_t crc;
PAYLOAD_INFO() : VID(1487)
{
magicnumber[0] = 0xFA;
magicnumber[1] = 0x11;
magicnumber[2] = 0x28;
magicnumber[3] = 0x33;
}
};