[英]Is there any way to control the padding between struct members (incl. bit field) in C++?
我正在解析網絡數據流,我想知道是否有任何方法可以將數據流直接映射到數據結構。
例如,我想如下定義RTP協議的數據結構。
class RTPHeader
{
int version:2; // The first two bits is version.
int P:1; // The next bits is an field P.
int X:1;
int CC:4;
int M:1;
int PT:7;
int sequenceNumber;
int64 timestamp;
.....
};
並以這種方式使用它。
RTPHeader header;
memcpy(&header, steamData, sizeof(header));
但是,由於C ++編譯器將在成員之間插入填充,有沒有辦法控制它,以便在成員之間不添加填充(包括位字段成員)?
這個問題不是如何擺脫結構的數據成員之間的填充字節,因為在我的例子中可能有位字段。
如果您能夠使用C ++ 11,則可以利用使用alignof
運算符實現的對齊控制。
如果您不能使用C ++ 11編譯器,那么可以幫助您的非標准替代方案; 在GCC中__attribute__(packed)
,和MSVC #pragma pack
。
如果您選擇的是GCC變體,則該屬性必須放在結構的末尾 :
class RTPHeader
{
int version:2; // The first two bits is version.
int P:1; // The next bits is an field P.
int X:1;
int CC:4;
int M:1;
int PT:7;
int sequenceNumber;
int64 timestamp;
.....
} __attribute__((packed)) ; // attribute here!
如果您選擇的是MSVC,則必須將該pragma放在struct 之前 :
#pragma pack(1) // pragma here!
class RTPHeader
{
int version:2; // The first two bits is version.
int P:1; // The next bits is an field P.
int X:1;
int CC:4;
int M:1;
int PT:7;
int sequenceNumber;
int64 timestamp;
.....
};
如果您的代碼必須同時編譯,唯一的方法(沒有C ++ 11 alignof
運算符)是條件編譯:
#ifdef MSVC
#pragma pack(1)
#endif
class RTPHeader
{
int version:2; // The first two bits is version.
int P:1; // The next bits is an field P.
int X:1;
int CC:4;
int M:1;
int PT:7;
int sequenceNumber;
int64 timestamp;
.....
#ifdef GCC
}__attribute__((packed));
#else
};
#endif
為避免插入填充字節,您可以使用
#pragma pack(push,n) // use n = 1 to have 1 Byte resolution
typedef struct {...}MY_STRUCT;
#pragma pack(pop)
這對我來說很好。
還要考慮Struct Member Alignment的編譯選項
/Zp1
但請記住,這會對整個項目產生影響。
只要你沒有要求這個代碼在任意機器上“工作” - 例如對int
所在的字節邊界(通常是4字節邊界)有限制的機器,那么使用
#pragma(pack)
應該工作,它在GCC以及Microsoft和“Microsoft插件兼容”編譯器(例如Intel的編譯器)中得到支持。
但請注意,並非所有處理器都支持未對齊訪問,因此啟動具有16位值的塊,然后是32位int
可能會導致問題。
我還會對sequencenumber使用一個大小的整數來確保它在每個編譯器中都是32位,而不是突然的16位或64位。
另請注意,C ++標准沒有說明位存儲在位域中的順序 - 或者說它們之間是否存在間隙。 雖然你可以期望根據字節順序存儲位域(小端機器首先從最低位開始,大端機器首先從最高位開始),但標准在這方面沒有說明任何內容。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.