开发者

Can wrapping a type in a struct cause additional padding? [duplicate]

开发者 https://www.devze.com 2023-04-01 15:30 出处:网络
This question already has answers here: Closed 11 years ago. Possible Duplicate: Size of struct with a single element
This question already has answers here: Closed 11 years ago.

Possible Duplicate:

Size of struct with a single element

Given any type A and the following struct:

struct S
{
    A a;
};

Are there any cases where sizeof(S) is g开发者_如何学JAVAreater than sizeof(A)?

For example, can sizeof(std::array<T, n>) be greater than sizeof(T[n])?


Being able to use A inside of S means that the compiler already has knowledge of the structure of A and has already added padding bytes to it. I see no reason for it to add further padding to S, as it already is aligned.


While the struct can be padded, on all systems I know, the compiler will pad so that the alignment of the structure is the same as the largest alignment of its members. It does this so that an array of the structure will always be correctly aligned.

So:

struct S 
{
   char a;
} // Size 1, no padding

struct S2 
{
   unsigned int a;
   char b;
} // Size 8, 3 bytes padding (assuming 32 bit integer)

Edit: Note, that compilers can also add internal padding, to keep the alignment of the data correct.

The C/C++ standard doesn't specify any of these detail. What you want is the C ABI (application binary interface) for the system you're running on, which should specify default layout for structs (compilers can choose to override this if they see fit, see also #pragma pack). For an example, look at the X86_64 ABI page 13, which states:

Aggregates and Unions Structures and unions assume the alignment of their most strictly aligned compo- nent. Each member is assigned to the lowest available offset with the appropriate alignment. The size of any object is always a multiple of the object‘s alignment. An array uses the same alignment as its elements, except that a local or global array variable of length at least 16 bytes or a C99 variable-length array variable always has alignment of at least 16 bytes. Structure and union objects can require padding to meet size and alignment constraints. The contents of any padding is undefined.


The relevant text is 5.3.3/2 "When applied to a class, the result is the number of bytes in an object of that class including any padding required for placing objects of that type in an array."

An implementation is allowed to add extra bytes for the purposes of array bound checks (e.g. "this is the 5th array member out of a total of 12", as this is within the leeway granted here and not explicitly banned by any other requirement.

(Presumably, that implementation would also store a "1 out of 1" indication for structs that aren't part of an array; in C++ the types S and S[1] are quite interchangable)


ISO/IEC 14882(10/2008) 1.8.5:

Unless it is a bit-field (9.6), a most derived object shall have a non-zero size and shall occupy one or more bytes of storage. Base class subobjects may have zero size.

This means that an empty struct has a size of 1 although the size of "all data members" (there are none) is zero, as would a zero-length bitfield (according to 9.6.2 this would have to be an unnamed bitfield, though).
Neither really applies though, as you did not ask for an empty struct, and your member is named (so it can't be zero-length).

Similar would be true if your a member was of type void, but 3.9.5 does not allow that ("[...] the void types are incomplete types (3.9.1). Objects shall not be defined to have an incomplete type").

So in short, as you said you are mostly interested about what the standard says: no, the standard does not explicitly define such a case.

However, it also does not forbid the compiler to add padding or apply alignment, and most compilers will pad/align structures to machine word size by default (unless explicitly told otherwise).


A struct can be padded (it's allowed for compilers do whatever they like, for example padding a six-octet type to eight to align with page boundaries). It's unlikely to happen though.

std::array will be bigger, because it stores some extra information in the class, like the array's length. Typing on auto-pilot; read std::vector without thinking.


If A is a byte then struct will align to the nearest boundary. Rather if A is smaller than a boundary then yes it will be bigger. EX a struct of RGB is the same size as a struct of RGBA.

I don't have sample code that will do that. You have to dump memory and see the holes. If you then assume that everything is size aligned and cast a structure onto a wad of memory you will have bad data. This is why WADs had padding for alignment. As your compositions get more complicated, the ability to close holes by the compiler is diminished. Eventually padding will be introduced and any assumptions of memory layout will become more and more wrong.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号