Packing of Struct Fields

Ali Çehreli acehreli at yahoo.com
Fri Oct 16 20:52:49 UTC 2020


On 10/16/20 1:32 PM, Per Nordlöw wrote:
> Why is `T.sizeof` 12 instead of 8 when `U.sizeof` is 8 in the following 
> example?
> 
> struct S
> {
>      int i;
>      bool b;
> }
> 
> struct T
> {
>      S s;
>      char c;
> }
> 
> struct U
> {
>      int i;
>      bool b;
>      char c;
> }
> 
> ?

I have a function that dumps member layout of structs, which someone may 
find useful:

   http://ddili.org/ders/d.en/memory.html#ix_memory..offsetof

It prints the following for these types:

=== Memory layout of 'S' (.sizeof: 8, .alignof: 4) ===
    0: int i
    4: bool b
    5: ... 3-byte PADDING
=== Memory layout of 'T' (.sizeof: 12, .alignof: 4) ===
    0: S s
    8: char c
    9: ... 3-byte PADDING
=== Memory layout of 'U' (.sizeof: 8, .alignof: 4) ===
    0: int i
    4: bool b
    5: char c
    6: ... 2-byte PADDING

Copied here:

struct S
{
     int i;
     bool b;
}

struct T
{
     S s;
     char c;
}

struct U
{
     int i;
     bool b;
     char c;
}

void printObjectLayout(T)()
         if (is (T == struct) || is (T == union)) {
     import std.stdio;
     import std.string;

     writefln("=== Memory layout of '%s'" ~
              " (.sizeof: %s, .alignof: %s) ===",
              T.stringof, T.sizeof, T.alignof);

     /* Prints a single line of layout information. */
     void printLine(size_t offset, string info) {
         writefln("%4s: %s", offset, info);
     }

     /* Prints padding information if padding is actually
      * observed. */
     void maybePrintPaddingInfo(size_t expectedOffset,
                                size_t actualOffset) {
         if (expectedOffset < actualOffset) {
             /* There is some padding because the actual offset
              * is beyond the expected one. */

             const paddingSize = actualOffset - expectedOffset;

             printLine(expectedOffset,
                       format("... %s-byte PADDING",
                              paddingSize));
         }
     }

     /* This is the expected offset of the next member if there
      * were no padding bytes before that member. */
     size_t noPaddingOffset = 0;

     /* Note: __traits(allMembers) is a 'string' collection of
      * names of the members of a type. */
     foreach (memberName; __traits(allMembers, T)) {
         mixin (format("alias member = %s.%s;",
                       T.stringof, memberName));

         const offset = member.offsetof;
         maybePrintPaddingInfo(noPaddingOffset, offset);

         const typeName = typeof(member).stringof;
         printLine(offset,
                   format("%s %s", typeName, memberName));

         noPaddingOffset = offset + member.sizeof;
     }

     maybePrintPaddingInfo(noPaddingOffset, T.sizeof);
}

void main() {
   printObjectLayout!S();
   printObjectLayout!T();
   printObjectLayout!U();
}

Ali



More information about the Digitalmars-d-learn mailing list