简体   繁体   中英

How to fill in struct paddings in C/C++?

Suppose I have the following struct:

typedef struct {
    int mID;
    struct in_addr mIP;
    size_t dataSize;
    // Another structure
    fairness_structure str;
    bool ack;
    bool stability;
    bool stop_message;
}HeaderType;

As you know, the size of a struct would vary due to its alignment. How to fill in the padding between fields with some data, say with zeros?

Just initialize the structure with memset, and the padding will be filled as well.

memset(&mystruct, 0, sizeof(HeaderType));

If you want to really only fill the pads, you can can cast the pointer to char* and do the arithmetics. But in this case you MUST know how the compiler padded the structure, or enforce it yourself with #pragma pack . You can use offsetof() macro to get the offset of struct members.

char *off = (char *)&mystruct + offsetof(HeaderType, ack);
char *pad_start = off + sizeof(mystruct.ack);
char *pad_end   = (char *)&mystruct + offsetof(HeaderType, stability);

Bedtime reading: The Lost Art of C Structure Packing

Controlling the contents of padding bits and bytes does not seem very useful. But if you write the contents of a structure to a file with a single write or fwrite call, You probably care about the padding and may want to make sure they have consistent values, preferably 0, at all times. Not that is matters when you read the contents back from the file, but in order for the file contents to be predictable and reproducible. Some development tools are known to produce unpredictable contents in object or executable files exactly for this reason, making it very difficult to rebuild from source and check signatures.

So if you really need this, you want a simple and portable method.

The bad news is the C Standard does not have a generic solution for this.

The only guaranty about the contents of padding bytes and bits the standard makes is for uninitialized structures of static storage. Padding is guarantied to be zero in this case (in a hosted environment). In practice, this is also true of initialized structures because it is simple enough for compiler writers to do so.

What about local structures with automatic storage? If they are not initialized, both fields and padding contents are indeterminate. If you just clear the bytes with a memset(&s, 0, sizeof(s)) the padding will be cleared and you can start modifying struct members... Bad news again: the C standard describes as Unspecified behaviour The value of padding bytes when storing values in structures or unions (6.2.6.1).

In other words, storing values in structure members can have side effects on the contents of padding bits and bytes. The compiler is allowed to generate code that does that and it may be more efficient to do so.

The method described by Marek beyond the simple memset is very cumbersome to use, especially if you have bitfields. In practice, clearing the structures before you initialize the fields manually seems the simplest way to achieve the purpose, and I have not seen a compilers that takes advantage of the Standard's leniency concerning the padding bytes. If you pass the structures by value, all bets are off as the compiler may generate code that does not copy the padding.

As a conclusion: if you use local structures, clear them with memset before use and do not pass them by value. There is no guaranty padding will keep a 0 value, but that's the best you can do.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM