Compound literal without initializer?

Discussion in 'C Programming' started by Lauri Alanko, Feb 16, 2011.

  1. Lauri Alanko

    Lauri Alanko Guest

    Hello.

    I'd like to have a macro NEW(t) that expands to an expression whose
    value is a pointer to a newly allocated object of type t that has
    automatic storage duration (when used inside a function). If an
    explicit initializer is provided, this is easy with a compound
    literal:

    #define NEWI(t,i) ((t[1]){i})

    However, I'm interested in the case where the object is filled in
    later in the code, and its initial value is irrelevant. Thus requiring
    a dummy initializer feels a bit ugly. The following is illegal, since
    an initializer list cannot be empty (why o why?):

    #define NEW(t) ((t[1]){})

    and the following only works if t is a scalar type:

    #define NEW(t) ((t[1]){0})

    C always requires an initializer, and there is no universal
    initializer. So I'm at my wits' end. Are there any portable solutions
    to this?

    Thanks,


    Lauri
     
    Lauri Alanko, Feb 16, 2011
    #1
    1. Advertising

  2. Lauri Alanko <> writes:

    > I'd like to have a macro NEW(t) that expands to an expression whose
    > value is a pointer to a newly allocated object of type t that has
    > automatic storage duration (when used inside a function). If an
    > explicit initializer is provided, this is easy with a compound
    > literal:
    >
    > #define NEWI(t,i) ((t[1]){i})


    I'd consider using (&(t){i}) instead since there would be fewer
    surprises if you happen to use the macro as an argument to sizeof or &
    (unlikely, I know).

    > However, I'm interested in the case where the object is filled in
    > later in the code, and its initial value is irrelevant. Thus requiring
    > a dummy initializer feels a bit ugly. The following is illegal, since
    > an initializer list cannot be empty (why o why?):
    >
    > #define NEW(t) ((t[1]){})
    >
    > and the following only works if t is a scalar type:
    >
    > #define NEW(t) ((t[1]){0})
    >
    > C always requires an initializer, and there is no universal
    > initializer.


    You've found the solution: {0} *is* a universal initialiser. Again, I'd
    probably opt for (&(t){0}) but I can't see why yours would not also
    work.

    You may be put off by the fact that some compilers warn about missing
    initialisers but the construct works with scalar and aggregate types
    alike.

    If the warnings get to be too much for you, I offer this ghastly kludge:

    #define NEW(t) (&(union { char dummy; t real; }){ .dummy = 0 }.real)

    (check for typos).

    <snip>
    --
    Ben.
     
    Ben Bacarisse, Feb 16, 2011
    #2
    1. Advertising

  3. Lauri Alanko

    Lauri Alanko Guest

    In article <>,
    Ben Bacarisse <> wrote:
    > > #define NEWI(t,i) ((t[1]){i})

    >
    > I'd consider using (&(t){i}) instead since there would be fewer
    > surprises if you happen to use the macro as an argument to sizeof or &
    > (unlikely, I know).


    Ah. I hadn't fully realized that you can use compound literals with
    _all_ types (even scalars), and that the result is always an lvalue. I
    wasn't really happy with the array hack in the first place.

    > > C always requires an initializer, and there is no universal
    > > initializer.

    >
    > You've found the solution: {0} *is* a universal initialiser.


    I had also forgotten that the initializers of a struct can be
    "flattened" and the braces need not follow the structure of the struct
    type. I was indeed scared by the compiler warnings and thought it was
    being too lax to only warn.

    I also hadn't known that "int i = { 0 };" is legal.

    > #define NEW(t) (&(union { char dummy; t real; }){ .dummy = 0 }.real)


    I think this is exactly the sort of a macrological kludge I was
    looking for. Thanks!


    Lauri
     
    Lauri Alanko, Feb 16, 2011
    #3
  4. Lauri Alanko

    Lauri Alanko Guest

    FAM literals?

    Somewhat related:

    Sadly, there is no direct way to get an object with non-allocated
    storage duration that has a structure type with flexible array
    members. This seems like the most obvious hack to get a FAM struct
    literal:

    #define list_(n) struct { int len; void* elems[n]; }
    typedef list_() list;
    #define LIST(n) (&(union { list_(n) i; list l; }){ .i = {n,{0}}}.l)
    list* lst = LIST(42);

    To my understanding this is not entirely portable (the two
    elems-fields might conceivably have different offsets due to bizarre
    padding decisions by the compiler), but is likely to work in practice
    everywhere where C99 is supported.

    Any comments, suggestions, condemnations?


    Lauri
     
    Lauri Alanko, Feb 16, 2011
    #4
    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. William Ahern

    lifetime of compound literal

    William Ahern, May 10, 2005, in forum: C Programming
    Replies:
    2
    Views:
    415
    Christian Kandeler
    May 11, 2005
  2. Luca Forlizzi

    array compound literal

    Luca Forlizzi, Feb 11, 2010, in forum: C Programming
    Replies:
    4
    Views:
    1,098
    Luca Forlizzi
    Feb 12, 2010
  3. Vincenzo Mercuri

    string literal initializer

    Vincenzo Mercuri, Jun 19, 2010, in forum: C Programming
    Replies:
    15
    Views:
    647
    Luca Forlizzi
    Jul 8, 2010
  4. Replies:
    1
    Views:
    584
  5. Christopher Collins

    Size of a compound literal array

    Christopher Collins, Sep 12, 2013, in forum: C Programming
    Replies:
    1
    Views:
    223
    Eric Sosman
    Sep 12, 2013
Loading...

Share This Page