Getting sizeof an anonymous struct declared inside a union

Discussion in 'C Programming' started by David Resnick, Oct 17, 2007.

  1. I'm faced with a header with anonymous structures declared inside a
    union like this:

    union msg {
    struct {
    int a;
    int b;
    } s1;

    struct {
    char c;
    double d;
    double e;
    } s2;
    };

    I want to apply the sizeof operator to one of these structs.
    Changing the header is not currently an option, alas.

    I currently can see two ways to do this as shown in this test program:

    #include <stdio.h>
    /* above union declaration here */
    int main(void)
    {
    union msg foo;
    printf("%lu\n", (unsigned long)sizeof(foo.s1));
    printf("%lu\n", (unsigned long)sizeof(((union msg*)(NULL))->s2));

    return 0;
    }

    Is the second legitimate? It compiles without complaint, but looks
    dodgy.
    I hate to create a fake instance of the union just to apply the sizeof
    operator.
    Or is there another way?

    Thanks,
    -David
     
    David Resnick, Oct 17, 2007
    #1
    1. Advertising

  2. David Resnick

    Guest

    On Oct 17, 6:07 pm, David Resnick <> wrote:
    > Is the second legitimate? It compiles without complaint, but looks
    > dodgy.

    Yes it is.
    Consider the following:
    int *p;
    printf("sizeof(*p) == sizeof(int) == %zu\n", sizeof *p);
    This would've been invalid code if what p pointed to was really
    accessed.
     
    , Oct 17, 2007
    #2
    1. Advertising

  3. David Resnick <> writes:

    > I'm faced with a header with anonymous structures declared inside a
    > union like this:
    >
    > union msg {
    > struct {
    > int a;
    > int b;
    > } s1;
    >
    > struct {
    > char c;
    > double d;
    > double e;
    > } s2;
    > };
    >
    > I want to apply the sizeof operator to one of these structs.
    > Changing the header is not currently an option, alas.
    >
    > I currently can see two ways to do this as shown in this test program:
    >
    > #include <stdio.h>
    > /* above union declaration here */
    > int main(void)
    > {
    > union msg foo;
    > printf("%lu\n", (unsigned long)sizeof(foo.s1));
    > printf("%lu\n", (unsigned long)sizeof(((union msg*)(NULL))->s2));
    >
    > return 0;
    > }
    >
    > Is the second legitimate?


    I think so, yes. Unless the union contains a variable length array,
    the operand of sizeof is not evaluated.

    > It compiles without complaint, but looks
    > dodgy.
    > I hate to create a fake instance of the union just to apply the sizeof
    > operator.
    > Or is there another way?


    You can use a compound literal (new in C99) which won't actually
    'make' anything either:

    sizeof (union msg){{0,0}}.s2;

    but this requires you to know how to initialise a 'union msg' (so the
    code changes if the structure changes) and you need C99. Since you
    carefully cast sizeof's result to unsigned long (rather then using
    %zu) I suspect you are not using C99.

    --
    Ben.
     
    Ben Bacarisse, Oct 17, 2007
    #3
  4. On Wed, 17 Oct 2007 16:44:36 +0100, Ben Bacarisse wrote:
    > You can use a compound literal (new in C99) which won't actually 'make'
    > anything either:
    >
    > sizeof (union msg){{0,0}}.s2;
    >
    > but this requires you to know how to initialise a 'union msg' (so the
    > code changes if the structure changes)


    All object and incomplete types can be initialised to {0}, whether
    they're arrays, structures, unions, or scalars.

    sizeof (int) {0} ==
    sizeof (int)
    sizeof (int [2]) {0} ==
    sizeof (int [2])
    sizeof (union { struct { union { int m; } u; } s; }) {0} ==
    sizeof (union { struct { union { int m; } u; } s; })
     
    =?iso-2022-kr?q?=1B=24=29CHarald_van_D=0E=29=26=0F, Oct 17, 2007
    #4
  5. writes:
    > On Oct 17, 6:07 pm, David Resnick <> wrote:
    >> Is the second legitimate? It compiles without complaint, but looks
    >> dodgy.

    > Yes it is.
    > Consider the following:
    > int *p;
    > printf("sizeof(*p) == sizeof(int) == %zu\n", sizeof *p);
    > This would've been invalid code if what p pointed to was really
    > accessed.


    Yes, it would have. Fortunately, the argument to sizeof is never
    evaluated unless it's a VLA.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Oct 17, 2007
    #5
  6. Harald van Dijk <> writes:

    > On Wed, 17 Oct 2007 16:44:36 +0100, Ben Bacarisse wrote:
    >> You can use a compound literal (new in C99) which won't actually 'make'
    >> anything either:
    >>
    >> sizeof (union msg){{0,0}}.s2;
    >>
    >> but this requires you to know how to initialise a 'union msg' (so the
    >> code changes if the structure changes)

    >
    > All object and incomplete types can be initialised to {0}, whether
    > they're arrays, structures, unions, or scalars.
    >
    > sizeof (int) {0} ==
    > sizeof (int)
    > sizeof (int [2]) {0} ==
    > sizeof (int [2])
    > sizeof (union { struct { union { int m; } u; } s; }) {0} ==
    > sizeof (union { struct { union { int m; } u; } s; })


    Duh! I tried that, and concluded that the rules must be different for
    compound literals, but it was just the compiler giving me a helpful
    warning.

    --
    Ben.
     
    Ben Bacarisse, Oct 17, 2007
    #6
  7. On Wed, 17 Oct 2007 16:36:44 +0000 (UTC), $)CHarald van D)&k
    <> wrote:

    > On Wed, 17 Oct 2007 16:44:36 +0100, Ben Bacarisse wrote:
    > > You can use a compound literal (new in C99) which won't actually 'make'
    > > anything either:
    > >
    > > sizeof (union msg){{0,0}}.s2;
    > >
    > > but this requires you to know how to initialise a 'union msg' (so the
    > > code changes if the structure changes)

    >
    > All object and incomplete types can be initialised to {0}, whether
    > they're arrays, structures, unions, or scalars.
    >

    Object types yes, and array of unknown size (but not VLA); but not the
    other incomplete types: tag-only struct/union, and void.

    - formerly david.thompson1 || achar(64) || worldnet.att.net
     
    David Thompson, Oct 29, 2007
    #7
  8. On Mon, 29 Oct 2007 01:02:24 +0000, David Thompson wrote:
    > On Wed, 17 Oct 2007 16:36:44 +0000 (UTC), $)CHarald van D)&k
    > <> wrote:
    >> All object and incomplete types can be initialised to {0}, whether
    >> they're arrays, structures, unions, or scalars.
    >>

    > Object types yes, and array of unknown size (but not VLA); but not the
    > other incomplete types: tag-only struct/union, and void.


    You can't define objects of undefined struct/union types or of void type
    anyway, so whether the initialiser would work if you could doesn't really
    matter, but VLAs are a definite exception. Thanks, I'll try to remember
    that.
     
    =?iso-2022-kr?q?=1B=24=29CHarald_van_D=0E=29=26=0F, Oct 29, 2007
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. JKop
    Replies:
    5
    Views:
    5,002
    Derek
    Oct 26, 2004
  2. Chris Fogelklou
    Replies:
    36
    Views:
    1,439
    Chris Fogelklou
    Apr 20, 2004
  3. Peter Dunker

    union in struct without union name

    Peter Dunker, Apr 26, 2004, in forum: C Programming
    Replies:
    2
    Views:
    924
    Chris Torek
    Apr 26, 2004
  4. Andreas Eibach
    Replies:
    4
    Views:
    1,130
    Andreas Eibach
    Oct 6, 2009
  5. Andreas Eibach
    Replies:
    5
    Views:
    451
    Bart van Ingen Schenau
    Oct 6, 2009
Loading...

Share This Page