views:

91

answers:

4

Is it possible to write a macro that has a type and a value as its input parameters (MACRO(type,value)), and returns a valid pointer to a location that holds the submitted value.

This macro should perform like the following function, but in a more generic manner:

int *val_to_ptr(int val){
    int *r = NULL;
    r = nm_malloc(sizeof(*r));
    *r = val;
    return r;
}

Where nm_malloc() is a failsafe malloc. The Macro usage should be compatible with this usage:

printf("%d",*MACRO(int,5));

Is it possible to achieve that ?

+3  A: 

If you're using gcc, you can use statement expressions:

#define MACRO(type,value) ({ type* t = nm_malloc(sizeof(*t)); *t = (value); t; })
KennyTM
+2  A: 

Perhaps (untested):

#define ALLOC_AND_INIT(T, val) *(T*)malloc(sizeof(T))=(val)

Usage

printf("%d\n", ALLOC_AND_INIT(int, 5));  // memory leak :)
Alex
printf("%d\n", *ALLOC_AND_INIT(int,5)); - This was the desired functionality.
Andrei Ciobanu
+2  A: 

Here's an implementation which is modelled on c++ templates

#define DEFINE_TEMPLATE(type) \
type * val_to_ptr_##type(type val){\
    type * ptr = NULL;\
    ptr = nm_malloc(sizeof(*ptr));\
    *ptr = val;\
    return ptr;\
}

#define USE_TEMPLATE(type,val)\
val_to_ptr_##type(val)

DEFINE_TEMPLATE(int);
int main(){
    printf("%d",*USE_TEMPLATE(int,5));
    return 0;
}

You'd have to explicitly define what types you're using it for, and would have to typedef things like unsigned int or double complex or the token paste won't work.

Alternately use

USE_TEMPLATE(type) val_to_ptr_##type

and call

USE_TEMPLATE(int)(5);

without having to worry about argument evaluation

Scott Wales
Is there any way to prevent multiple instantiation of the same function ?
Andrei Ciobanu
@Andrei you might be able to declare the function `inline`, i.e. `inline type * val_to_ptr_##type` in the `DEFINE_TEMPLATE` macro. I think that would still be an error if you defined it for the same type more than once in the same file though.
Scott Wales
Alternately if you want to get really complicated create a macro `#define DECLARE_TEMPLATE(type) type* val_to_ptr_##type(type val)`which you could use multiple times for the same type, and ensure you link in a file which has `DEFINE_TEMPLATE` used for that type.
Scott Wales
+1  A: 

Any of the solutions using malloc() will cause a memory leak in the example you gave. However, this simple solution, using C99 compound literals, does not:

#define MACRO(type, val) (&(type){val})
caf