在 C++ 的联合中动态分配内存给数组

Dynamically allocate memory to arrays in a union in C++

我正在使用 union 来填充 char 类型消息缓冲区中的一些消息字段。如果消息的长度不变,它就可以正常工作。请参阅下面的简化代码示例。

问题是,我的消息可以有可变长度。具体来说,const N 将在运行时决定。有没有办法通过为 buf?

动态分配内存来继续使用联合

我正在探索智能指针,但到目前为止还没有成功。

const int N = 4;

struct repeating_group_t {
  uint8_t field1;
  uint8_t field2;
}rpt_group;

struct message_t
{
    union
    {
        char buf[2 + 2*N];
        struct {
          uint8_t header;
          uint8_t block_len;
          std::array<repeating_group_t, N> group;
        };
    };
};

int main()
{ 
    message_t msg;

    msg.header    = 0x32;
    msg.block_len = 8;

    for (auto i = 0; i < N; i++)
    {
      msg.group[i].field1 = i;
      msg.group[i].field2 = 10*i;
    } 

    // msg.buf is correctly filled

    return 0;
}

您不能在运行时计算 N,因为 c 数组(您的 buf)和 std::array 在其类型中都有大小信息。

此外 - 使用 union 进行(反)序列化不是一个好习惯 - 你的结构的大小将取决于它被编译的给定机器上所需的对齐等等...你可以添加 packed属性来克服它,但你仍然有很多平台依赖性问题。

关于可变长度 - 您需要编写自定义(反)序列化程序来理解和 store/read 该大小信息以在另一端重新创建该容器。

您想将这些消息传递到哪里?

如评论所说,使用std::vector

int main() {
     // before C++17 use char
     std::vector<std::byte> v.
     v.push_back(0x32);
     v.push_back(8);
     for (auto i = 0; i < N; i++) {
         v.push_back(i);
         const uint16_t a = 10 * i;
         // store uint16_t in big endian
         v.push_back(a >> 16);
         v.push_back(a & 0xff);
     } 
}

对于自定义数据类型,您可以提供自己的流式或容器式容器和重载 operator>> 或您为数据类型选择的其他自定义函数。

struct Message{
    std::vector<std::byte> v; 
    Message& push8(uint8_t t) { ... }
    // push 16 bits little endian
    Message& push16le(uint16_t t) { ... }
    // push 16 bits big endian
    Message& push16be(uint16_t t) { ... }
    // etc
    Message& push(const Repeating_group& t) {
       v.push_back(t.field1);
       v.push_back(t.field2);
       return v;
    }
    // etc.
};

int main(){ 
     Message v;
     v.push8(0x32).push8(8);
     for (...) {
         v.push(Repeating_group(i, i * 10));
     }
 }