【问题标题】:Initializing a const array in a struct in C++在 C++ 中初始化结构中的 const 数组
【发布时间】:2013-01-17 10:47:06
【问题描述】:


我必须在道具上工作。二进制文件格式,想用结构体来实现。
我的结构中需要恒定的字节序列,而 atm 我不知道如何实现这一点。

我想过这样的事情:

#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”应该看起来像这样(在内存中),不考虑本示例中的字节顺序:

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)

但没有按预期工作。

有没有办法在不计算每个结构成员的内存大小、分配新内存和复制每个成员的情况下完成这项工作?

我使用 g++ 4.6.3。

请注意, 托马斯

更新:
@bikeshedder 提供的 c++11 解决方案运行良好,但只能使用 g++ 4.7 或更高版本进行编译。

【问题讨论】:

  • 你说“不按预期工作(ed)”。你得到什么结果?哪里错了?
  • 我认为你需要const uint8_t PAYLOAD_INFO::magicnumber[4] = ...。虽然不是 100%。
  • @WhozCraig 那么好吧! :P

标签: c++ arrays struct constants


【解决方案1】:

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

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

也就是说,正如@bikeshedder 下面提到的那样,静态数据是单独存储在内存中的,因此当您创建结构的新实例时,该实例不会在实例的内存位置中包含幻数,因此您使用 @987654322 @ 不会像你期望的那样工作。

【讨论】:

    【解决方案2】:

    我建议不要将任何类型的 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;
        }
    };
    

    【讨论】:

    • 我使用 c++11,现在得到一个“抱歉,未实现:非静态数据成员初始化程序”。切换到 g++ 4.7.2 修复了它。在我的情况下,字节顺序并不重要,因为我最终从提供的带有“writeToFile”的二进制库中意识到,在写入之前使用了 POSIX htonX。谢谢你的帮助。
    猜你喜欢
    • 2014-08-08
    • 2010-09-23
    • 2010-12-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多