Initializing a const array in a structure in C ++


I have to work on support. binary file format and want to implement it using structures.
I need a constant sequence of bytes in my structures and I don't understand how to implement this.

I thought of something similar:

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

      

At the end, "pldInst" should look something like this (in memory) disregarding the byte in this example:

0x00000000:  0xFA, 0x11 , 0x28 , 0x33
0x00000004:  0x00, 0x05 , 0x05 , 0xCF
0x00000008:  0x34, 0x23 , 0x5a , 0x54

      

I've already tried the "default" approach:

#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)

      

but doesn't work as expected.

Is there a way to do this without calculating the memory size of each member of the structure, allocating new memory, and copying each member?

I am using g ++ 4.6.3.

Regard, Thomas

UPDATE:
The C ++ 11 solution provided by @bikeshedder works pretty well, but it only compiles with g ++ 4.7 or higher.

+3


source to share


2 answers


I would recommend against any kind of dumping structs

into raw memory unless you are using some kernel interface that is guaranteed to run on the same computer and should be used that way.

It's not portable (endian issues), each compiler does it a little differently, and the performance really isn't that much better. In general, this does not justify this bad practice.

The reason why your example code doesn't work is because of static members. Since static members are not part of an object (but a class), only UMID

and are written crc

.

struct PAYLOAD_INFO {
    const uint8_t magicnumber[4] = { 0xFA, 0x11, 0x28, 0x33 };
    uint16_t UMID;
    const uint16_t VID = 1487 ;
    uint32_t crc;
};

      



This code only works in C ++ 11, but since you are including cstdint

, I assume you are already using this C ++ version. If you are not using C ++ 11, you need to initialize the elements in the constructor, and you shouldn't use const

for a magic number because it cannot be initialized. (See 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;
};

      



For C ++ 98, you need to do:

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

      

+3


source


Your statics are currently just defining global static. You need to add a class specifier to define statics as part of your class.

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

      



However, as @bikeshedder mentions below, the statics are kept separate in memory, so when you create a new instance of your struct, that instance will not include magic numbers in the instance's memory location, so your usage writeToFile

will not work as you expect.

+4


source







All Articles