Initializing compound type containing opaque type

Discussion in 'C Programming' started by Nate Eldredge, Oct 1, 2008.

  1. Consider the following pseudo-code:

    #include <opaque.h>

    struct foo {
    int a;
    opaque_t op;
    int b;
    };

    struct foo blah = { 17, /* ??? */ , 23 };

    Here we suppose that `opaque_t' is defined in <opaque.h> as some type
    not known to us, or which we cannot rely on. In particular, it may be
    a scalar or compound type. The goal is to initialize `blah' in such a
    way that `blah.a == 17' and `blah.b == 23'. We don't care about the
    value of `blah.op'.

    It seems to me that there is no way to do this in standard C. Is this
    correct, or am I missing something?

    A workaround would be to rearrange the members of `struct foo' as

    struct foo2 {
    int a;
    int b;
    opaque_t op;
    };

    struct foo2 blah2 = { 17, 23 };

    I believe this is legal, but I could be wrong. My compiler warns
    about a missing initializer, but accepts the code.

    If `opaque_t' is known to be a compound type, we could write

    struct foo blah3 = { 17, { }, 23 };

    which again provokes a missing initializer warning but is accepted.
    Again I am curious whether it is actually legal.

    I thought of this issue after reading a post here a couple weeks ago,
    "Exception handling crashes or exits" by Fabiano Sidler,
    <48c4e24d$>, in which the poster wants a struct
    with a jmp_buf as one member. He initializes that member with { 0 },
    which is certainly non-portable. But I wondered if there is a
    portable way to do the same thing.

    If not, it seems like it might be useful for the authors of <opaque.h>
    to provide a macro which is suitable as an initializer for opaque_t.
    E.g. <opaque.h> might contain

    typedef opaque_t struct {
    int x,
    double d;
    };

    #define OPAQUE_INITIALIZER { 0, 0.0 }

    so that one could write

    struct foo blah = { 17, OPAQUE_INITIALIZER, 23 };

    In particular, this could be a useful extension for library authors to
    provide for opaque library types (e.g. jmp_buf, FILE, etc).

    Any thoughts?
     
    Nate Eldredge, Oct 1, 2008
    #1
    1. Advertising

  2. Nate Eldredge

    Guest

    On Oct 2, 12:05 am, Nate Eldredge <> wrote:
    > Consider the following pseudo-code:
    >
    > #include <opaque.h>
    >
    > struct foo {
    > int a;
    > opaque_t op;
    > int b;
    >
    > };
    >
    > struct foo blah = { 17, /* ??? */ , 23 };
    >
    > Here we suppose that `opaque_t' is defined in <opaque.h> as some type
    > not known to us, or which we cannot rely on. In particular, it may be
    > a scalar or compound type. The goal is to initialize `blah' in such a
    > way that `blah.a == 17' and `blah.b == 23'. We don't care about the
    > value of `blah.op'.
    >
    > It seems to me that there is no way to do this in standard C. Is this
    > correct, or am I missing something?
    >
    > A workaround would be to rearrange the members of `struct foo' as
    >
    > struct foo2 {
    > int a;
    > int b;
    > opaque_t op;
    >
    > };
    >
    > struct foo2 blah2 = { 17, 23 };
    >
    > I believe this is legal, but I could be wrong. My compiler warns
    > about a missing initializer, but accepts the code.


    Yes, it's legal.
    (note: In POSIX it wouldn't be; *_t are reserved identifiers)

    > If `opaque_t' is known to be a compound type, we could write
    >
    > struct foo blah3 = { 17, { }, 23 };
    >
    > which again provokes a missing initializer warning but is accepted.
    > Again I am curious whether it is actually legal.


    Also legal.

    > I thought of this issue after reading a post here a couple weeks ago,
    > "Exception handling crashes or exits" by Fabiano Sidler,
    > <48c4e24d$>, in which the poster wants a struct
    > with a jmp_buf as one member. He initializes that member with { 0 },
    > which is certainly non-portable. But I wondered if there is a
    > portable way to do the same thing.


    Yes, jmp_buf foo = {0};

    Though that'd initialize all members to 0, 0.0 or NULL depending on
    type, recursively applied for any aggregate

    > If not, it seems like it might be useful for the authors of <opaque.h>
    > to provide a macro which is suitable as an initializer for opaque_t.


    Well, it is legal, so it's not useful.

    > E.g. <opaque.h> might contain

    <snip>
     
    , Oct 1, 2008
    #2
    1. Advertising

  3. On Wed, 01 Oct 2008 14:05:53 -0700, Nate Eldredge <>
    wrote:

    >Consider the following pseudo-code:
    >
    >#include <opaque.h>
    >
    >struct foo {
    > int a;
    > opaque_t op;
    > int b;
    >};
    >
    >struct foo blah = { 17, /* ??? */ , 23 };
    >
    >Here we suppose that `opaque_t' is defined in <opaque.h> as some type
    >not known to us, or which we cannot rely on. In particular, it may be
    >a scalar or compound type. The goal is to initialize `blah' in such a
    >way that `blah.a == 17' and `blah.b == 23'. We don't care about the
    >value of `blah.op'.
    >
    >It seems to me that there is no way to do this in standard C. Is this
    >correct, or am I missing something?
    >
    >A workaround would be to rearrange the members of `struct foo' as
    >
    >struct foo2 {
    > int a;
    > int b;
    > opaque_t op;
    >};
    >
    >struct foo2 blah2 = { 17, 23 };
    >
    >I believe this is legal, but I could be wrong. My compiler warns
    >about a missing initializer, but accepts the code.


    An insufficient quantity of initializers is specifically allowed
    (6.7.8-19 and -21). Compilers are allowed to issue diagnostic
    messages for correct code. Some do so when assigning an int to a char
    or when using gets. These are not so much warnings (a term not
    defined in the standard) but more like reminders to the programmer
    that something is "unusual" and worth a second look. As long as the
    code complies with the standard, the compiler is obligated to accept
    it.

    >
    >If `opaque_t' is known to be a compound type, we could write
    >
    >struct foo blah3 = { 17, { }, 23 };
    >
    >which again provokes a missing initializer warning but is accepted.
    >Again I am curious whether it is actually legal.
    >
    >I thought of this issue after reading a post here a couple weeks ago,
    >"Exception handling crashes or exits" by Fabiano Sidler,
    ><48c4e24d$>, in which the poster wants a struct
    >with a jmp_buf as one member. He initializes that member with { 0 },
    >which is certainly non-portable. But I wondered if there is a


    It is portable, for both aggregate and scalar objects. See 6.7.8-16,
    -11, and -19.

    >portable way to do the same thing.
    >
    >If not, it seems like it might be useful for the authors of <opaque.h>
    >to provide a macro which is suitable as an initializer for opaque_t.
    >E.g. <opaque.h> might contain
    >
    >typedef opaque_t struct {
    > int x,
    > double d;
    >};
    >
    >#define OPAQUE_INITIALIZER { 0, 0.0 }
    >
    >so that one could write
    >
    >struct foo blah = { 17, OPAQUE_INITIALIZER, 23 };
    >
    >In particular, this could be a useful extension for library authors to
    >provide for opaque library types (e.g. jmp_buf, FILE, etc).


    {0} should suffice. If the object requires non-zero initialization,
    the library should provide an initialization function.

    --
    Remove del for email
     
    Barry Schwarz, Oct 1, 2008
    #3
  4. Eric Sosman <> writes:

    > Nate Eldredge wrote:
    >> Consider the following pseudo-code:
    >>
    >> #include <opaque.h>
    >>
    >> struct foo {
    >> int a;
    >> opaque_t op;
    >> int b;
    >> };
    >>
    >> struct foo blah = { 17, /* ??? */ , 23 };
    >>
    >> Here we suppose that `opaque_t' is defined in <opaque.h> as some type
    >> not known to us, or which we cannot rely on. In particular, it may be
    >> a scalar or compound type. The goal is to initialize `blah' in such a
    >> way that `blah.a == 17' and `blah.b == 23'. We don't care about the
    >> value of `blah.op'.

    >
    > In C99 you could use a "compound literal:"
    >
    > struct foo blah = (struct foo){.a = 17, .b = 23};
    >
    > (Double-check my syntax; I'm typing this hurriedly.)


    My compiler says "error: initializer element is not constant". It
    does work if it is moved inside a function, so that blah is auto, but
    that's of course entirely different. (Anyway, in that case we could
    just initialize blah.a and blah.b by hand.)

    > In C90 you could initialize the unknown member to "zero of
    > the appropriate type:"
    >
    > struct foo blah = { 17, { 0 }, 23 };
    >
    > Some compilers may emit warnings for too few initializers, but
    > the initialization is valid; if opaque_t is compound, its sub-
    > elements are initialized to appropriate zeroes. The warnings may
    > be a nuisance, but they do no actual harm.


    Interesting, so the OP was correct after all. I never knew about
    "zero of the appropriate type". I assumed that would be wrong if
    opaque_t turned out to be a scalar type, or a compound whose first
    member was also compound, but apparently not. Those clever language
    designers, always one step ahead. :)

    Thanks to all who replied.
     
    Nate Eldredge, Oct 1, 2008
    #4
  5. Nate Eldredge

    Guest

    On Oct 2, 12:05 am, Nate Eldredge <> wrote:
    > Consider the following pseudo-code:
    >
    > #include <opaque.h>
    >
    > struct foo {
    > int a;
    > opaque_t op;
    > int b;
    >
    > };
    >
    > struct foo blah = { 17, /* ??? */ , 23 };
    >
    > Here we suppose that `opaque_t' is defined in <opaque.h> as some type
    > not known to us, or which we cannot rely on. In particular, it may be
    > a scalar or compound type. The goal is to initialize `blah' in such a
    > way that `blah.a == 17' and `blah.b == 23'. We don't care about the
    > value of `blah.op'.
    >
    > It seems to me that there is no way to do this in standard C. Is this
    > correct, or am I missing something?


    Whoops, I forgot to reply to this question at my post.
    In C99 you can.

    struct foo blah = { .a = 17, .b = 23 };

    Mr Sossman mentioned compound literals, but I'm unsure why he didn't
    mention this which is even simpler.

    You can also do this for array elements

    char foo[2] = { .[1] = 'a' };
     
    , Oct 2, 2008
    #5
  6. Nate Eldredge

    Guest

    On Oct 2, 1:28 am, Eric Sosman <> wrote:
    ....
    > In C99 you could use a "compound literal:"
    >
    > struct foo blah = (struct foo){.a = 17, .b = 23};
    >
    > (Double-check my syntax; I'm typing this hurriedly.)


    I think you mean

    struct foo blah = *(struct foo[]){ { .a = 17, .b = 23 } };
     
    , Oct 2, 2008
    #6
  7. Nate Eldredge <> writes:

    > Eric Sosman <> writes:
    >
    >> Nate Eldredge wrote:
    >>> Consider the following pseudo-code:
    >>>
    >>> #include <opaque.h>
    >>>
    >>> struct foo {
    >>> int a;
    >>> opaque_t op;
    >>> int b;
    >>> };
    >>>
    >>> struct foo blah = { 17, /* ??? */ , 23 };
    >>>
    >>> Here we suppose that `opaque_t' is defined in <opaque.h> as some type
    >>> not known to us, or which we cannot rely on. In particular, it may be
    >>> a scalar or compound type. The goal is to initialize `blah' in such a
    >>> way that `blah.a == 17' and `blah.b == 23'. We don't care about the
    >>> value of `blah.op'.

    >>
    >> In C99 you could use a "compound literal:"
    >>
    >> struct foo blah = (struct foo){.a = 17, .b = 23};
    >>
    >> (Double-check my syntax; I'm typing this hurriedly.)


    Not allowed, I think, at file scope.

    > My compiler says "error: initializer element is not constant".


    Just use the "initialiser list" rather than providing a compound
    literal. I.e. write:

    struct foo blah = {.a = 17, .b = 23};

    This works for file-scope declarations as well as block-scope ones.

    > It
    > does work if it is moved inside a function, so that blah is auto, but
    > that's of course entirely different.


    Yes. 6.7.8 paragraph 13 permits an expression of "compatible
    structure or union type" when the object has automatic storage. You
    have to read though to paragraph 16 to get to the text:

    "Otherwise, the initializer for an object that has aggregate or
    union type shall be a brace-enclosed list of initializers..."

    to see that a compound literal is not allowed as the sole "top-level"
    initialiser for an object with static storage duration. At least that
    is my explanation of your error message.

    --
    Ben.
     
    Ben Bacarisse, Oct 2, 2008
    #7
  8. writes:
    <snip>
    > You can also do this for array elements
    >
    > char foo[2] = { .[1] = 'a' };


    There's no dot. I.e.:

    char foo[2] = { [1] = 'a' };

    --
    Ben.
     
    Ben Bacarisse, Oct 2, 2008
    #8
  9. William Pursell <> writes:

    > On 1 Oct, 22:05, Nate Eldredge <> wrote:
    >> Consider the following pseudo-code:
    >>
    >> #include <opaque.h>
    >>
    >> struct foo {
    >>        int a;
    >>        opaque_t op;
    >>        int b;
    >>
    >> };
    >>

    >
    > If opaque_t is truly opaque, and not specified
    > in opaque.h, then the compiler won't accept
    > this definition of struct foo. If the compiler
    > is accepting this, then the header is specifying
    > opaque_t completely, so (I would argue) has
    > misnamed it because it isn't opaque.


    By "opaque" I mean an object whose format and contents are not
    intended to be used by the programmer, and are subject to change.
    This is how I've heard it used in the past.

    jmp_buf is an example. Certainly you can open up <setjmp.h> and find
    out how it is defined on your system; maybe it's a struct with a
    member for each of your CPU's registers. But you can't use any of
    that information in a portable program, since on another system, or a
    later version of the same system, it may be defined differently, or
    used differently by the library, so in a more general sense you don't
    really "know" how it's defined. All you "know" about jmp_buf is that
    you can create one using setjmp() and pass it to longjmp() later on.
    From the programmer's point of view it's just a magic cookie.

    Other examples in the standard library would be time_t and FILE.
    div_t is a library type that I would not call opaque; it is documented
    as being a struct with two members, `quot' and `rem', whose types and
    meanings are well described and guaranteed to be the same in all
    conforming implementations.
     
    Nate Eldredge, Oct 2, 2008
    #9
  10. William Pursell <> writes:

    > On 2 Oct, 00:45, Ben Bacarisse <> wrote:
    >> writes:
    >>
    >> <snip>
    >>
    >> > You can also do this for array elements

    >>
    >> > char foo[2] = { .[1] = 'a' };

    >>
    >> There's no dot.  I.e.:
    >>
    >>   char foo[2] = { [1] = 'a' };

    >
    > Is that C99? I thought that was a gnu extension.


    Yes, it is C99:

    designation:
    designator-list =

    designator-list:
    designator
    designator-list designator

    designator:
    [ constant-expression ]
    . identifier

    --
    Ben.
     
    Ben Bacarisse, Oct 2, 2008
    #10
  11. Nate Eldredge

    James Kuyper Guest

    William Pursell wrote:
    > On 2 Oct, 00:45, Ben Bacarisse <> wrote:

    ....
    >> char foo[2] = { [1] = 'a' };

    >
    > Is that C99? ...


    Yes.
     
    James Kuyper, Oct 2, 2008
    #11
  12. William Pursell <> writes:
    > On 1 Oct, 22:05, Nate Eldredge <> wrote:
    >> Consider the following pseudo-code:
    >>
    >> #include <opaque.h>
    >>
    >> struct foo {
    >>        int a;
    >>        opaque_t op;
    >>        int b;
    >>
    >> };
    >>

    >
    > If opaque_t is truly opaque, and not specified
    > in opaque.h, then the compiler won't accept
    > this definition of struct foo. If the compiler
    > is accepting this, then the header is specifying
    > opaque_t completely, so (I would argue) has
    > misnamed it because it isn't opaque.


    There are different kinds of opacity. Consider type FILE, defined in
    <stdio.h>. That header must completely specify the type -- but code
    that uses it is expected to depend only on the standard functions and
    the fact that it's an object type.

    >> struct foo blah = { 17, /* ??? */ , 23 };
    >>
    >> Here we suppose that `opaque_t' is defined in <opaque.h> as some type
    >> not known to us, or which we cannot rely on.

    >
    > I don't understand what you mean by "not known to us". If
    > the compiler can get the definition from opaque_t, then
    > you can, too!


    Sure you *can* -- but then the next version of the library defines it
    differently and your code breaks.

    It's both common and reasonable to define an "opaque" type that's
    completely defined in the header, just by *asking* authors of client
    code not to cheat by peeking at its innards. (Which is not to say
    that there aren't other reasonable approaches.)

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Oct 2, 2008
    #12
  13. On 2 Oct, 17:28, Keith Thompson <> wrote:

    <snip>

    > There are different kinds of opacity.  Consider type FILE, defined in
    > <stdio.h>.  That header must completely specify the type


    why? user code only needs a pointer

    > -- but code
    > that uses it is expected to depend only on the standard functions and
    > the fact that it's an object type.


    <snip>

    --
    Nick Keighley
     
    Nick Keighley, Oct 3, 2008
    #13
  14. Nick Keighley <> writes:
    > On 2 Oct, 17:28, Keith Thompson <> wrote:
    >
    > <snip>
    >
    >> There are different kinds of opacity.  Consider type FILE, defined in
    >> <stdio.h>.  That header must completely specify the type

    >
    > why? user code only needs a pointer
    >
    >> -- but code
    >> that uses it is expected to depend only on the standard functions and
    >> the fact that it's an object type.

    >
    > <snip>


    The standard requires FILE to be

    an object type capable of recording all the information needed to
    control a stream, including its file position indicator, a pointer
    to its associated buffer (if any), an _error indicator_ that
    records whether a read/write error has occurred, and an
    _end-of-file indicator_ that records whether the end of the file
    has been reached

    The declaration of FILE in <stdio.h> needn't indicate *how* it records
    all that information. For example, it could be declared as

    typedef unsigned char[_FILE_BYTES] FILE;

    and the library code that uses it could cast the FILE* to, say,
    _FILE_STRUCT* to access the information. Most implementations don't
    do this; for one thing, the macro definitions for putc and getc are
    going to expose some of the inner details anyway.

    Since user code only needs to use FILE*, not type FILE itself, an
    implementation that declares:

    typedef void FILE;

    would be perfectly sensible, except that it would violate the
    standard's requirement. In my opinion, the standard over-specifies
    this, but it's not a huge deal.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Oct 3, 2008
    #14
  15. Nate Eldredge wrote:
    > Eric Sosman <> writes:
    > > In C90 you could initialize the unknown member to "zero of
    > > the appropriate type:"
    > >
    > > struct foo blah = { 17, { 0 }, 23 };
    > >
    > > Some compilers may emit warnings for too few initializers, but
    > > the initialization is valid; if opaque_t is compound, its sub-
    > > elements are initialized to appropriate zeroes. The warnings may
    > > be a nuisance, but they do no actual harm.

    >
    > Interesting, so the OP was correct after all. I never knew about
    > "zero of the appropriate type". I assumed that would be wrong if
    > opaque_t turned out to be a scalar type, or a compound whose first
    > member was also compound, but apparently not. Those clever language
    > designers, always one step ahead. :)


    {0} initializer is wrong if the first member of opaque_t is an array
     
    Szabolcs Nagy, Oct 3, 2008
    #15
  16. Szabolcs Nagy <> writes:

    > Nate Eldredge wrote:
    >> Eric Sosman <> writes:
    >> > In C90 you could initialize the unknown member to "zero of
    >> > the appropriate type:"
    >> >
    >> > struct foo blah = { 17, { 0 }, 23 };
    >> >
    >> > Some compilers may emit warnings for too few initializers, but
    >> > the initialization is valid; if opaque_t is compound, its sub-
    >> > elements are initialized to appropriate zeroes. The warnings may
    >> > be a nuisance, but they do no actual harm.

    >>
    >> Interesting, so the OP was correct after all. I never knew about
    >> "zero of the appropriate type". I assumed that would be wrong if
    >> opaque_t turned out to be a scalar type, or a compound whose first
    >> member was also compound, but apparently not. Those clever language
    >> designers, always one step ahead. :)

    >
    > {0} initializer is wrong if the first member of opaque_t is an array


    Is it really? gcc -ansi -pedantic accepts it.
     
    Nate Eldredge, Oct 3, 2008
    #16
  17. Nate Eldredge

    Guest

    On Oct 4, 12:41 am, Nate Eldredge <> wrote:
    > Szabolcs Nagy <> writes:
    >
    >
    >
    > > Nate Eldredge wrote:
    > >> Eric Sosman <> writes:
    > >> > In C90 you could initialize the unknown member to "zero of
    > >> > the appropriate type:"

    >
    > >> > struct foo blah = { 17, { 0 }, 23 };

    >
    > >> > Some compilers may emit warnings for too few initializers, but
    > >> > the initialization is valid; if opaque_t is compound, its sub-
    > >> > elements are initialized to appropriate zeroes. The warnings may
    > >> > be a nuisance, but they do no actual harm.

    >
    > >> Interesting, so the OP was correct after all. I never knew about
    > >> "zero of the appropriate type". I assumed that would be wrong if
    > >> opaque_t turned out to be a scalar type, or a compound whose first
    > >> member was also compound, but apparently not. Those clever language
    > >> designers, always one step ahead. :)

    >
    > > {0} initializer is wrong if the first member of opaque_t is an array

    >
    > Is it really? gcc -ansi -pedantic accepts it.



    No it isn't, it's correct.

    When not all of an object is initialized, the rest is initialized as
    if it were 'static'.
     
    , Oct 4, 2008
    #17
  18. writes:

    > On Oct 4, 12:41 am, Nate Eldredge <> wrote:
    >> Szabolcs Nagy <> writes:
    >>
    >>
    >>
    >> > Nate Eldredge wrote:
    >> >> Eric Sosman <> writes:
    >> >> > In C90 you could initialize the unknown member to "zero of
    >> >> > the appropriate type:"

    >>
    >> >> > struct foo blah = { 17, { 0 }, 23 };

    >>
    >> >> > Some compilers may emit warnings for too few initializers, but
    >> >> > the initialization is valid; if opaque_t is compound, its sub-
    >> >> > elements are initialized to appropriate zeroes. The warnings may
    >> >> > be a nuisance, but they do no actual harm.

    >>
    >> >> Interesting, so the OP was correct after all. I never knew about
    >> >> "zero of the appropriate type". I assumed that would be wrong if
    >> >> opaque_t turned out to be a scalar type, or a compound whose first
    >> >> member was also compound, but apparently not. Those clever language
    >> >> designers, always one step ahead. :)

    >>
    >> > {0} initializer is wrong if the first member of opaque_t is an array

    >>
    >> Is it really? gcc -ansi -pedantic accepts it.

    >
    >
    > No it isn't, it's correct.
    >
    > When not all of an object is initialized, the rest is initialized as
    > if it were 'static'.


    Right, but in this example we have something like

    typedef struct {
    int arr[5];
    double d;
    } opaque_t;

    struct foo {
    int a;
    opaque_t op;
    int b;
    };

    struct foo blah = { 17, {0} , 23 };

    which on the face of it would appear to initialize blah.op.arr with 0,
    which doesn't make sense, instead of { 0 }, which would.

    So if I'm understanding correctly, there is a feature in C whereby
    {0}, "zero of appropriate type", is valid as an initializer for any
    type, which for scalar types initializes to 0, and for aggregate types
    initializes each element, recursively, to 0. Can someone provide a
    pointer to the standard or another reference which describes this more
    fully?

    (Incidentally, I'm not sure if I'm correctly using the terms "compound
    type" and "aggregate type". I intend them both to refer to a type
    which is a structure, union or array.)
     
    Nate Eldredge, Oct 4, 2008
    #18
  19. Richard Heathfield <> writes:

    > Nate Eldredge said:


    >> So if I'm understanding correctly, there is a feature in C whereby
    >> {0}, "zero of appropriate type", is valid as an initializer for any
    >> type, which for scalar types initializes to 0, and for aggregate types
    >> initializes each element, recursively, to 0. Can someone provide a
    >> pointer to the standard or another reference which describes this more
    >> fully?

    >
    > It's covered fully in 3.5.7 Initialization (C89) and 6.7.8 Initialization
    > (C99).


    Thanks. I bit the bullet and bought a copy of the standard, and now
    it makes sense. I had been under the impression that when
    initializing an aggregate which contains other aggregates, you had to
    enclose the values for each sub-aggregate in its own set of braces.
    But it appears that if you just supply a list of values, the compiler
    will "flatten" the aggregate in order to assign them to members. I
    didn't know about that. Thus given

    struct bar {
    struct {
    int x;
    } a;
    struct {
    struct {
    int y;
    } q;
    } b;
    };

    you can write

    struct bar argh = { { 1 }, { { 2 } } };

    reflecting the recursive structure of struct bar, or you can write

    struct bar argh = { 1, 2 };

    which flattens it; both leave argh.a.x == 1 and argh.b.q.y == 2. I
    has thought only the first form was legal.

    And as an additional bit of syntactic sugar, when initializing a
    non-aggregate type, you can enclose the value in braces, which I also
    didn't know about. So

    int foo = { 42 };

    is legal.

    Finally, 0 is a legal value for any non-aggregate type, be it integer,
    floating point, or pointer. So combining all this, {0} is a legal
    initializer for any type, and has the effect of initializing all
    members to zero.

    Have I understood it correctly? Thanks!
     
    Nate Eldredge, Oct 4, 2008
    #19
  20. Nate Eldredge <> writes:
    > Richard Heathfield <> writes:

    [...]
    >> It's covered fully in 3.5.7 Initialization (C89) and 6.7.8 Initialization
    >> (C99).

    >
    > Thanks. I bit the bullet and bought a copy of the standard, and now
    > it makes sense.

    [...]

    I hope you knew that a post-standard draft, which includes the C99
    standard with the three Technical Corrigenda merged into it, is
    available at no charge at
    <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf>.

    I've paid for PDF copies of the C90 and C99 standards myself, but
    n1256 is the one I use as a reference most often.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Oct 4, 2008
    #20
    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. dna
    Replies:
    0
    Views:
    1,233
  2. Martin Meier

    opaque - Bedeutung ?

    Martin Meier, Sep 10, 2004, in forum: Java
    Replies:
    3
    Views:
    1,503
    Eric Sosman
    Sep 10, 2004
  3. Brian Tozer

    Semi-opaque colored background

    Brian Tozer, Feb 8, 2004, in forum: HTML
    Replies:
    11
    Views:
    4,805
    Steve Pugh
    Feb 9, 2004
  4. Labora

    Opaque data type

    Labora, Nov 17, 2004, in forum: C Programming
    Replies:
    1
    Views:
    346
    Michael Mair
    Nov 17, 2004
  5. Richard Weeks

    implementing an opaque type

    Richard Weeks, Feb 26, 2007, in forum: C Programming
    Replies:
    3
    Views:
    347
    Chris Thomasson
    Feb 27, 2007
Loading...

Share This Page