struct fill with values

时间:2015-11-12 12:24:13

标签: c++ struct

编辑2:关于XY问题:

在二进制协议中,我需要发送8个字节。这些字节可以包含8或16位长的整数,也可以包含1,2或3位长的标志。

为了简化它,我更喜欢使用结构:

struct MakeCoffeeCmd
{
    UINT8 sugar : 2;
    UINT8 milk : 1;
    UINT16 liters;
};

所以我可以像这样使用它:

cmd.sugar = 1;
cmd.milk = 0;
cmd.liters = 42;

send(cmd);

问题是:糖,牛奶和升在8字节数组中定义了位置,每个未使用的位必须设置为1.

现在,我使用:

UINT8 cmd[8];
memset(&cmd, ~0, sizeof(cmd));

cmd[1] &= sugar << 4;
cmd[1] &= milk << 1;
*((UINT16*)(cmd + 3)) = liters;

send(cmd);

原始问题:

我想创建一个8字节长的结构。由于原因,我只关心第二个和第三个字节,所有其他字节必须设置为0xFF。

应该如下所示:0xFF [Byte1] [Byte2] 0xFF 0xFF 0xFF 0xFF 0xFF

我试过这样,但看起来太丑了。

struct mystruct
{
    mystruct() : should_be_ff(0xFF), should_also_be_ff(0xFF), sould_be_ff_too(0xFFFFFFFF) {}
    UINT8  should_be_ff;
    UINT16 important_values;
    UINT8  should_also_be_ff;
    UINT32 should_be_ff_too;
 }

我可以使用位字段进行填充,但是我无法设置正确的值。

我更喜欢这样的事情:

struct mystruct
{
    0xFF;
    UINT16 important_values;
    0xFFFFFF;
}

有什么想法吗?

编辑1:

我需要一些专有的二进制协议,我无法改变。这只是一个例子,有更复杂的结构,包括标志和位字段。在数组中使用它们会很难看。

我已修改打包(希望)消除填充错误。

5 个答案:

答案 0 :(得分:8)

  

我想创建一个8字节长的结构。

您的结构可能不是8个字节长。你可以在成员之间填充,也可以在最后填充。

没有标准方法可以保证结构的大小为8个字节。

如果您只需要8个字节,则可以使用数组:

uint8_t arr[8];                    // exactly 8 bytes
memset(arr, ~0, sizeof arr);       // set all bits to 1 i.e. every byte to 0xff
uint16_t foo = 123u;               // some important 2-byte value
memcpy(arr + 1, &foo, sizeof foo); // copy the 2-byte value to the second and third index

请记住,字节的顺序取决于架构的字节顺序。

关于编辑2:

您当然可以使用这样的结构来表示您自己的应用程序中的协议消息。但要根据协议发送它,必须先将其转换为数组。必须逐场完成。由于填充和别名问题,转换不会在平台上正确执行。我建议使用char数组,因为char类型有关于别名的特殊规则,这使得它们更易于使用。

要将struct实例的未使用位设置为1,最简单的解决方案可能是memset

MakeCoffeeCmd object;
memset(&object, ~0, sizeof object);

之后,您可以设置使用的字段。然后将每个字段复制到数组中正确的插槽。

答案 1 :(得分:1)

怎么样:

struct mystruct
{
    UINT8 ignore1;
    std::array<UINT8, 2> data;
    std::array<UINT8, 5> ignore2;

    mystruct()
        : ignore1(0xFF)
    {
        ignore2.fill(0xFF);
    }
};

如果std :: array有一个填充构造函数,那么它就更清晰了。

答案 2 :(得分:1)

使用gcc,您可以执行此操作,以实施紧密包装:

struct __attribute__((__packed__)) my_struct 
{
    uint8_t  field1=0xff;
    uint16_t field2=0xabcd; // or whatever you need
    uint8_t  field3=0xff;
    uint32_t field4=0xffffffff;
};

有关使用__attribute__的详细信息,请查看文档: https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#Common-Type-Attributes

答案 3 :(得分:0)

我有这样的想法:

struct mystruct{
 mystruct(uint16_t impval=0){
   memset(m_data,0xff,sizeof(m_data));
   important() = impval;
 }
 void* data(){
   return m_data;
 }
 uint16_t& important(){
   return *reinterpret_cast<uint16_t*>(m_data+1);
 }
private:
uint8_t m_data[8];
};
当然,它可以做得更好,更便携,但没有时间atm

答案 4 :(得分:0)

这个选项怎么样:

 uint32_t arr[2];
 uint32_t inportant_flag = 123u;
 arr[0] = 0xFF0000FF + (inportant_flag<<8);
 arr[1] = 0xFFFFFFFF;