是否应该使用宏而不是灵活的数组成员?
Should one be using macros instead of flexible array members?
让我们假设如下:
我想为 UDP packets 创建一个结构。每个帧通常由一个以太网报头、一个 IP 报头、一个 UDP 报头和一个可选的有效载荷组成,最后是 FCS(帧校验和序列)。
有效负载长度为 unknown/flexible。
这意味着在创建结构时,有效负载必须是它的最后一个成员 (flexible array member)。因此,FCS 没有立足之地。
所以我想了想还有什么可能。
我想出了以下代码:
#define UDP_PKT(name, payload_length) struct __attribute((__packed__)) \
{ \
struct ether_header eth; \
struct ip iph; \
struct udphdr udph; \
unsigned char payload[payload_length]; \
u_int32_t fcs; \
} name;
因为这是不允许的:
struct __attribute__((__packed__)) udp_packet
{
struct ether_header eth;
struct ip iph;
struct udphdr udph;
unsigned char payload[]; // fam, must always be the last member
u_int32_t fcs;
};
我的问题:这是我必须在结构中包含 FCS 而没有固定数组(有效负载)大小的唯一可能性吗?
如果是这样,这是一个好的解决方案吗?这被认为是好的做法吗?
具有灵活数组成员的 struct
的大小是在运行时确定的,因此您的第一种方法也行不通。解决方案是在您准备好为线路序列化您的 struct
时将 FCS 放在缓冲区的末尾:
struct __attribute__((__packed__)) udp_packet {
struct ether_header eth;
struct ip iph;
struct udphdr udph;
u_int32_t fcs;
unsigned char payload[]; // Move fcs up
};
void serialize_udp_packet(const udp_packet* p) {
// Compute buffer size, and allocate the buffer
// Place the header into the buffer
// Copy the payload into the buffer
// Place FCS into the buffer at the end
}
您甚至可以从 udp_packet
中完全排除 fcs
,并且仅在序列化 struct
时才计算它。这种方法的一个优点是您可以自由地改变有效载荷,而不必一直将 FCS
同步到更改后的有效载荷。
为有效负载和校验和分配内存。使用指针访问校验和。简单高效
让我们假设如下:
我想为 UDP packets 创建一个结构。每个帧通常由一个以太网报头、一个 IP 报头、一个 UDP 报头和一个可选的有效载荷组成,最后是 FCS(帧校验和序列)。
有效负载长度为 unknown/flexible。
这意味着在创建结构时,有效负载必须是它的最后一个成员 (flexible array member)。因此,FCS 没有立足之地。
所以我想了想还有什么可能。
我想出了以下代码:
#define UDP_PKT(name, payload_length) struct __attribute((__packed__)) \
{ \
struct ether_header eth; \
struct ip iph; \
struct udphdr udph; \
unsigned char payload[payload_length]; \
u_int32_t fcs; \
} name;
因为这是不允许的:
struct __attribute__((__packed__)) udp_packet
{
struct ether_header eth;
struct ip iph;
struct udphdr udph;
unsigned char payload[]; // fam, must always be the last member
u_int32_t fcs;
};
我的问题:这是我必须在结构中包含 FCS 而没有固定数组(有效负载)大小的唯一可能性吗?
如果是这样,这是一个好的解决方案吗?这被认为是好的做法吗?
具有灵活数组成员的 struct
的大小是在运行时确定的,因此您的第一种方法也行不通。解决方案是在您准备好为线路序列化您的 struct
时将 FCS 放在缓冲区的末尾:
struct __attribute__((__packed__)) udp_packet {
struct ether_header eth;
struct ip iph;
struct udphdr udph;
u_int32_t fcs;
unsigned char payload[]; // Move fcs up
};
void serialize_udp_packet(const udp_packet* p) {
// Compute buffer size, and allocate the buffer
// Place the header into the buffer
// Copy the payload into the buffer
// Place FCS into the buffer at the end
}
您甚至可以从 udp_packet
中完全排除 fcs
,并且仅在序列化 struct
时才计算它。这种方法的一个优点是您可以自由地改变有效载荷,而不必一直将 FCS
同步到更改后的有效载荷。
为有效负载和校验和分配内存。使用指针访问校验和。简单高效