C++ 是否有一种保证方法可以避免基类和派生类之间的填充?
我正在开发一个网络程序,该程序将处理具有报头部分和有效负载部分的数据包。标头长度可变,根据网络条件添加或删除扩展段。用户数据部分是普通字节缓冲器,尽管在分组构造或使用期间可以将其视为某种结构或其他结构 我希望有一个基类来构建和操作报头,如果需要插入扩展字段,报头字节(可能)向前或向后移动,以及一个包含用户数据的派生类。例如:C++ 是否有一种保证方法可以避免基类和派生类之间的填充?,c++,memory-alignment,struct-member-alignment,C++,Memory Alignment,Struct Member Alignment,我正在开发一个网络程序,该程序将处理具有报头部分和有效负载部分的数据包。标头长度可变,根据网络条件添加或删除扩展段。用户数据部分是普通字节缓冲器,尽管在分组构造或使用期间可以将其视为某种结构或其他结构 我希望有一个基类来构建和操作报头,如果需要插入扩展字段,报头字节(可能)向前或向后移动,以及一个包含用户数据的派生类。例如: class hdr { public: const void *start( void ) { return uint8_t(pBuf) + siz
class hdr {
public:
const void *start( void ) { return uint8_t(pBuf) + sizeof(pBuf) - SIZEOF_HEADER - pExtBytes; }
private:
size_t pExtBytes;
uint32_t pBuf[16]; // header data goes here, shifted to the END of the buffer, adjacent the beginning of the derived class
// NO PADDING HERE!
} ;
class payload1 : public hdr {
public:
private:
uint8_t pData[128];
} ;
class payload2 : public hdr {
public:
private:
uint16_t pData[12];
} ;
是否有一种标准方法可以保证hdr
和payload1
或payload2
之间没有填充,这样我就可以将start()
传递到write()
,并将报头和连续的有效负载发送到网络?例如,如果(sizeof(hdr)%BIG\u STANDARD\u ALIGNMENT)==0)
则hdr
的派生类将在没有任何额外填充的情况下启动
另一种方法是使用分散/聚集I/O,但这似乎是一个复杂的设置,我不确定它是否能够将数据包片段收集在一起,以便在单个UDP数据包中传输。没有这种方法。使用带有
char pBuf[]
的非继承结构作为最后一个成员,并在需要时为其分配相应的大小。IMHO,使用缓冲区(如uint8_t
)传输数据。编写从缓冲区加载类
/结构
的方法。由于填充、对齐和vtable问题(以及其他可能性),请不要使用类或结构进行直接传输。谢谢,@Serge。经过更多的挖掘,我认为你是对的:没有语言保证的方法可以做到这一点。(当然,您可以让它与任何特定的编译器一起工作,也可以与一系列好的编译器一起工作,但规范并不要求它)。因此,尽管在“准备传输”代码路径中包含memcpy()
让我感到痛苦,但另一种选择(自定义程序集?)更糟糕。不管怎样,CPU现在比网络快。@DaveM您可以使用联合来进行数组映射。