Discussion:
new expression for C
(too old to reply)
Thiago Adams
2017-05-15 13:50:46 UTC
Permalink
Raw Message
I would like to have new expression for C.
Just to use 1 line of code instead of two.

Point pt = { 1, 2 };

Point* p;

p = new (Point) {1, 2};

"new" followed by compound literal. The sizeof of the
object of the compound literal is allocated and initialized.

the two lines replaces are

p = malloc(sizeof (Point));
if (p) *p = (Point) {1, 2};

int * p = new (int[100]){0};

The problem:

The problem I see is when we wan't a different allocator. (This happens in C++), then we need more rules to explain how to allocated, how
to override the new for a type for arrays for alignment, etc...
C++ has several options for new operator and still growing.
(http://en.cppreference.com/w/cpp/memory/new/operator_new)

I don't want several options.

My suggestion ,more precisely, is not to add new expression now, but
to say I would like a better syntax for it.
The problem is the syntax, the solution I don't know yet.

Maybe an optional function name after new

int * p = new(malloc) (int[100]){void};

if empty it would use malloc.

Could be with more args for especial allocators.

int * p = new(_aligned_malloc, 8) (int[100]){void};

So new could be something like an special macro.
Can we do it with macros?
GOTHIER Nathan
2017-05-15 15:02:11 UTC
Permalink
Raw Message
On Mon, 15 May 2017 06:50:46 -0700 (PDT)
Post by Thiago Adams
I would like to have new expression for C.
Just to use 1 line of code instead of two.
Dynamic allocation is most of the time a bad solution when you already know
that the size of the object required can be defined before the execution.
Post by Thiago Adams
Point pt = { 1, 2 };
Point* p;
p = new (Point) {1, 2};
Opaque structure is also a bad solution when you expect to access to its
members at any point of execution.

If you need C++ features just use C++ but don't blame C for being incomplete
because C aim to be concise rather than bloated with extra features that can be
avoided with C skills.
Thiago Adams
2017-05-15 17:21:20 UTC
Permalink
Raw Message
Post by GOTHIER Nathan
On Mon, 15 May 2017 06:50:46 -0700 (PDT)
Post by Thiago Adams
I would like to have new expression for C.
Just to use 1 line of code instead of two.
Dynamic allocation is most of the time a bad solution when you already know
that the size of the object required can be defined before the execution.
I do a lot of allocation of polymorphic nodes for an AST.
Tim Rentsch
2017-05-15 18:35:34 UTC
Permalink
Raw Message
Post by Thiago Adams
I would like to have new expression for C.
Just to use 1 line of code instead of two.
Point pt = { 1, 2 };
Point* p;
p = new (Point) {1, 2};
"new" followed by compound literal. The sizeof of the
object of the compound literal is allocated and initialized.
It's easy to provide this functionality with a
macro and a couple of static inline functions.
Exercise for the reader.
Thiago Adams
2017-05-15 18:48:15 UTC
Permalink
Raw Message
Post by Tim Rentsch
Post by Thiago Adams
I would like to have new expression for C.
Just to use 1 line of code instead of two.
Point pt = { 1, 2 };
Point* p;
p = new (Point) {1, 2};
"new" followed by compound literal. The sizeof of the
object of the compound literal is allocated and initialized.
It's easy to provide this functionality with a
macro and a couple of static inline functions.
Exercise for the reader.
But, using gcc extensions?
Using variadic macros?

Give me a tip :)
Tim Rentsch
2017-05-16 09:15:12 UTC
Permalink
Raw Message
Post by Thiago Adams
Post by Tim Rentsch
Post by Thiago Adams
I would like to have new expression for C.
Just to use 1 line of code instead of two.
Point pt = { 1, 2 };
Point* p;
p = new (Point) {1, 2};
"new" followed by compound literal. The sizeof of the
object of the compound literal is allocated and initialized.
It's easy to provide this functionality with a
macro and a couple of static inline functions.
Exercise for the reader.
But, using gcc extensions?
Using variadic macros?
Give me a tip :)
What I wrote was something like

p = NEW_INITIALLY( ((Point){ 1, 2 }) );

It did not use any gcc extensions or variadic macros; as far as
the macro processing goes I'm pretty sure it was C90 compatible.
Of course C99 is needed for the compound literal.

What I wrote didn't do anything fancy with types - the result of
a call on NEW_INITIALLY() is a (void*). A more sophisticated
solution might have separated out the type as a separate
argument, and used variadic arguments for the initializer values,
but I didn't explore anything along those lines.

The outer function was something like

static inline void *
allocate_and_copy( void *s, size_t n ){
return copy_it( malloc( n ), s, n );
}

You should be able to fill in the few remaining gaps without too
much difficulty.
Thiago Adams
2017-05-16 13:13:06 UTC
Permalink
Raw Message
Post by Tim Rentsch
Post by Thiago Adams
Post by Tim Rentsch
Post by Thiago Adams
I would like to have new expression for C.
Just to use 1 line of code instead of two.
Point pt = { 1, 2 };
Point* p;
p = new (Point) {1, 2};
"new" followed by compound literal. The sizeof of the
object of the compound literal is allocated and initialized.
It's easy to provide this functionality with a
macro and a couple of static inline functions.
Exercise for the reader.
But, using gcc extensions?
Using variadic macros?
Give me a tip :)
What I wrote was something like
p = NEW_INITIALLY( ((Point){ 1, 2 }) );
It did not use any gcc extensions or variadic macros; as far as
the macro processing goes I'm pretty sure it was C90 compatible.
Of course C99 is needed for the compound literal.
What I wrote didn't do anything fancy with types - the result of
a call on NEW_INITIALLY() is a (void*). A more sophisticated
solution might have separated out the type as a separate
argument, and used variadic arguments for the initializer values,
but I didn't explore anything along those lines.
The outer function was something like
static inline void *
allocate_and_copy( void *s, size_t n ){
return copy_it( malloc( n ), s, n );
}
You should be able to fill in the few remaining gaps without too
much difficulty.
Thanks, I forgot that I could use the extra parenthesis to make
just 1 macro argument.
But then, I tried with variadic macros and it worked as well.


static inline void* allocate_and_copy( void *s, size_t n )
{
void* pNew = malloc(n);
if (pNew)
{
memcpy(pNew, s, n);
}

return pNew ;
}

#define NEW1(X) allocate_and_copy(&X, sizeof(X))
#define NEW2(...) allocate_and_copy(&(__VA_ARGS__), sizeof(__VA_ARGS__))

typedef struct
{
int x;
int y;
} Point;

int main()
{
Point* p = NEW1(((Point) { 1, 2 }));

printf("x = %d y = %d", p->x, p->y);
p = NEW2((Point) {1, 2});
*p = POINT_INIT;
return 0;
}


The extra job I would like to have in C is :

typedef struct
{
int x = 1;
int y = 2;
} Point;

Point *p = NEW((Point){});

The pattern I can use with this macro is:

#define POINT_INIT ((Point) { 1, 2 })

Point* p = NEW1(POINT_INIT);
Point* p = NEW2(POINT_INIT);

Considering that this macro works, I don't want
to add it anymore to C.

Just the default initializer.
Point *p = NEW((Point){});

Loading...