如何在C++中把结构映射到字符正确的方法

How to map structure to char proper method in C++

本文关键字:字符 方法 映射 结构 C++      更新时间:2023-10-16

在C中,我被用来处理char*,我将一些表示网络数据包的结构映射到char*。然后我只需要分配数据包参数并通过网络发送:

更新-我忘记添加我有一些有效载荷

struct packet {
   uint64_t id __attribute__((packed)); 
   uint64_t something __attribute__((packed));
   short flags __attribute__((packed));
   // here follows payload with variable length
};
...
char *payload = get_payload();
size_t payload_size = get_payload_size();//doesnt matter how
char *data = malloc(sizeof(struct packet)+payload_size);
struct packet *pkt = (struct packet *)data;
pkt->id = 123;
pkt->something = get_something();
pkt->flags = FLAG | FLAG2;
memcpy(data+sizeof(struct packet), payload, payload_size);
send(data, sizeof(struct packet)+payload_size);

现在我想用一些不错的C++特性来实现这一点(如果有更好的方法的话)我在C++中能做的最好的改变是使用new而不是malloc。

char *data = new char[sizeof(struct packet)];//rest is same

好的,这叫做对象序列化。。我发现有几个例子总是使用boost,但我不能使用。。C++中难道没有一种原生的方法来实现这一点吗?

没有理由创建char*pkt*。您创建并发送一个对象,如:

packet pkt;  // create automatic object
pkt.id = 123;
pkt.something = get_something();
pktflags = FLAG | FLAG2;
// here we cast the address of pkt to a char* so we can send it
send(reinterpret_cast<char*>(&pkt), sizeof(packet));

编辑:

由于问题已更新为在struct数据的末尾添加有效载荷,您将不得不使用与在C中相同的方法。当您向上new指针时,语法将为

char * data = new char[sizeof(packet) + payload_size];

此外,当像在C中那样使用struct时,C++中不需要struct关键字。您可以按名称使用它。

我不喜欢您的原始代码依赖于非标准扩展__attribute__((packed))的方式。由于没有标准的方法要求struct完全没有填充,因此将结构复制到缓冲区的唯一符合标准的方法是单独复制每个成员。

这启发了我编写一个c++11帮助程序,将可变数量的变量复制到char数组中。为了帮助使用它,一个助手来计算这些变量的总大小(这里已经完成了)。使用这些助手,您可以轻松地将struct的成员复制到缓冲区中,而不需要打包struct

// variadic sizeof
// mostly same as https://stackoverflow.com/a/12666815/2079303
constexpr std::size_t sizeof_all() {
    return 0;
}
template <typename Head, typename... Tail>
constexpr std::size_t sizeof_all(const Head& head, const Tail&... tail) {
    return sizeof head + sizeof_all(tail...);
}
// variadic memcpy
void memcpy_all(char*) {}
template <typename Head, typename... Tail>
void memcpy_all(char* out, const Head& head, const Tail&... tail) {
    auto offset = sizeof head;
    std::memcpy(out, &head, offset);
    memcpy_all(out + offset, tail...);
}
// to use
packet p;
std::size_t buffer_size = sizeof_all(p.id, p.something, p.flags) + payload_size;
char* data = new char[buffer_size];
memcpy_all(data, p.id, p.something, p.flags);

现在,您只需要关注endianness。