Compound literal without initializer?

L

Lauri Alanko

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
 
B

Ben Bacarisse

Lauri Alanko said:
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>
 
L

Lauri Alanko

#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.
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
 
L

Lauri Alanko

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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top