gpt4 book ai didi

结构中的 C++ 可变长度数组

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:57:44 26 4
gpt4 key购买 nike

我正在编写一个程序来创建、发送、接收和解释 ARP 数据包。我有一个表示 ARP header 的结构,如下所示:

struct ArpHeader
{
unsigned short hardwareType;
unsigned short protocolType;
unsigned char hardwareAddressLength;
unsigned char protocolAddressLength;
unsigned short operationCode;
unsigned char senderHardwareAddress[6];
unsigned char senderProtocolAddress[4];
unsigned char targetHardwareAddress[6];
unsigned char targetProtocolAddress[4];
};

这仅适用于长度为 6 的硬件地址和长度为 4 的协议(protocol)地址。地址长度也在 header 中给出,因此为了正确起见,结构必须如下所示:

struct ArpHeader
{
unsigned short hardwareType;
unsigned short protocolType;
unsigned char hardwareAddressLength;
unsigned char protocolAddressLength;
unsigned short operationCode;
unsigned char senderHardwareAddress[hardwareAddressLength];
unsigned char senderProtocolAddress[protocolAddressLength];
unsigned char targetHardwareAddress[hardwareAddressLength];
unsigned char targetProtocolAddress[protocolAddressLength];
};

这显然行不通,因为地址长度在编译时是未知的。模板结构也不是一个选项,因为我想填充结构的值,然后将它从 (ArpHeader*) 转换为 (char*) 以获得可以在网络上发送或转换的字节数组从 (char*) 到 (ArpHeader*) 的接收字节数组,以便对其进行解释。

一个解决方案是创建一个类,其中所有 header 字段作为成员变量,一个函数创建一个字节数组,表示可以在网络上发送的 ARP header ,以及一个仅采用字节数组的构造函数(接收到网络)并通过读取所有 header 字段并将它们写入成员变量来解释它。这不是一个很好的解决方案,因为它需要更多的代码。

相反,UDP header 的类似结构很简单,因为所有 header 字段的大小都是已知的。我用

#pragma pack(push, 1)
#pragma pack(pop)

围绕结构声明,以便我实际上可以做一个简单的 C 风格转换来获取要在网络上发送的字节数组。

有没有我可以在这里使用的解决方案,它接近于结构,或者至少不需要比结构更多的代码?我知道结构中的最后一个字段(如果它是一个数组)不需要特定的编译时大小,我可以使用类似的东西来解决我的问题吗?只需将这 4 个数组的大小留空即可编译,但我不知道这将如何实际运行。从逻辑上讲,它无法工作,因为如果第一个数组的大小未知,编译器将不知道第二个数组从哪里开始。

最佳答案

您想要一个相当低级别的东西,一个 ARP 数据包,并且您正在尝试找到一种正确定义数据结构的方法,以便您可以将 blob 转换为该结构。相反,您可以在 blob 上使用接口(interface)。

struct ArpHeader {
mutable std::vector<uint8_t> buf_;

template <typename T>
struct ref {
uint8_t * const p_;
ref (uint8_t *p) : p_(p) {}
operator T () const { T t; memcpy(&t, p_, sizeof(t)); return t; }
T operator = (T t) const { memcpy(p_, &t, sizeof(t)); return t; }
};

template <typename T>
ref<T> get (size_t offset) const {
if (offset + sizeof(T) > buf_.size()) throw SOMETHING;
return ref<T>(&buf_[0] + offset);
}

ref<uint16_t> hwType() const { return get<uint16_t>(0); }
ref<uint16_t> protType () const { return get<uint16_t>(2); }
ref<uint8_t> hwAddrLen () const { return get<uint8_t>(4); }
ref<uint8_t> protAddrLen () const { return get<uint8_t>(5); }
ref<uint16_t> opCode () const { return get<uint16_t>(6); }

uint8_t *senderHwAddr () const { return &buf_[0] + 8; }
uint8_t *senderProtAddr () const { return senderHwAddr() + hwAddrLen(); }
uint8_t *targetHwAddr () const { return senderProtAddr() + protAddrLen(); }
uint8_t *targetProtAddr () const { return targetHwAddr() + hwAddrLen(); }
};

如果您需要 const 的正确性,您可以删除 mutable,创建一个 const_ref,并将访问器复制到非 const 版本,并使 const 版本返回 const_refconst uint8_t *

关于结构中的 C++ 可变长度数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25938046/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com