Is there any way to control the padding between struct members (incl. bit field) in C++?

谁说我不能喝 提交于 2019-12-01 02:59:30
Mats Petersson

As long as you have no requirement that this code "works" on arbitrary machines - e.g. machines that have restrictions as to what byte boundaries an int sits on (typically a 4 byte boundary), then using

 #pragma(pack)

should work, and it's supported in GCC as well as Microsoft and "Microsoft plug in compatible" compilers (Such as Intel's compiler).

But do note that unaligned access is not supported on all processors, so starting a block with a 16-bit value, followed by a 32-bit int is possibly going to cause problems.

I would also use a sized integer for sequencenumber to ensure it's 32-bits in EVERY compiler, and not suddenly 16 or 64 bits.

Note also that the C++ standard does not state anything about the order that the bits are stored in a bitfield - or for that matter if there are gaps between them or not. Although you can expect the bitfields to be stored according to the byte-order (little endian machines start with the lowest bits first, big endian machines start with the highest order bits first), the standard does not state anything in that respect.

If you're able to use C++11, you can take advantage of the align control implemented with the alignof operator.

If you cannot use a C++11 compiler, there's non-standard alternatives that can help you; in GCC the __attribute__(packed), and with MSVC the #pragma pack.

If your choice is the GCC variant, the attribute must be placed at the end of the struct:

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!

If your choice is the MSVC one, the pragma must be placed before the 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;
    .....
};

If your code must be compiled in both, the only way (without C++11 alignof operator) is the conditional compilation:

#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

To avoid an insertion of padded bytes you can use

#pragma pack(push,n)   // use n = 1 to have 1 Byte resolution

typedef struct {...}MY_STRUCT;

#pragma pack(pop)

This worked fine for me.

Also consider the compiling options for Struct Member Alignment

/Zp1

But keep in mind that this will have an impact to your whole project.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!