在C ++中初始化struct中的const数组

时间:2013-02-02 02:06:47

标签: c++ arrays struct const


我必须在道具上工作。二进制文件格式,并希望通过使用结构来实现它 我需要在我的结构中使用恒定的字节序列,并且我不知道如何实现它。

我想到了类似的东西:

#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或更高版本编译。

2 个答案:

答案 0 :(得分:4)

您的静态目前只是定义全局静态。您需要添加一个类说明符来定义要成为类的一部分的静态。

const uint8_t PAYLOAD_INFO::magicnumber[4] = { 0xFA, 0x11 , 0x28 , 0x33 };

也就是说,正如@bikeshedder在下面提到的那样,静态分别存储在内存中,所以当你创建一个新的struct实例时,该实例不会在实例的内存位置中包含幻数,所以你使用{{ 1}}将无法按预期工作。

答案 1 :(得分:3)

我建议不要将任何类型的structs转换为原始内存,除非你使用的是一些内核接口,它保证在同一台机器上运行并且应该以这种方式使用。

这不是可移植的(字节序问题),每个编译器都有一点不同,性能确实不是那么好。总而言之,这并不能成为这种不良行为的理由。

您的代码示例不起作用的原因是静态成员。由于静态成员不是对象(但是类)的一部分,因此只有UMIDcrc被写入。

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;
    }
};