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

Reply via email to