Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

c

padding

I'm working on parsing network data stream, I'm wondering if there is any way I can map the data stream directly to the data structure.

For example, I want to define the data structure for an RTP protocol as follows.

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;
   .....
};

And using it this way.

RTPHeader header;
memcpy(&header, steamData, sizeof(header));

But as the C++ compiler will insert padding between the members, is there any way to control that so that no padding are added between members (including the bit field members)?

This question is NOT a duplicate of How to get rid of padding bytes between data members of a struct because there can be bit fields in my example.

like image 637
ZijingWu Avatar asked Sep 06 '13 08:09

ZijingWu


People also ask

How can we prevent padding in structure?

In Structure, sometimes the size of the structure is more than the size of all structures members because of structure padding. Note: But what actual size of all structure member is 13 Bytes. So here total 3 bytes are wasted. So, to avoid structure padding we can use pragma pack as well as an attribute.

How is structure padding done in C?

Structure Padding in C: The structure padding is automatically done by the compiler to make sure all its members are byte aligned. Here 'char' is only 1 byte but after 3 byte padding, the number starts at 4 byte boundary. For 'int' and 'double', it takes up 4 and 8 bytes respectively.

Why do struct types in C sometimes contain padding?

The structural padding is an in-built process that is automatically done by the compiler. Sometimes it required to avoid the structure padding in C as it makes the size of the structure greater than the size of the structure members.

How do you add padding to a structure?

structure AThe compiler will insert a padding byte after the char to ensure short int will have an address multiple of 2 (i.e. 2 byte aligned). The total size of structa_t will be sizeof(char) + 1 (padding) + sizeof(short), 1 + 1 + 2 = 4 bytes.


1 Answers

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
like image 61
PaperBirdMaster Avatar answered Sep 21 '22 00:09

PaperBirdMaster