views:

92

answers:

2

Is it possible to rewrite the following code, so that it would be ISO C compliant ? The following macros are doing a malloc & init for a given type and value.

The current code works with the gcc compilers (uses a gcc extension), but it's not standard. If I use -pedantic, I receive warnings.

#ifdef __GNUC__

#define NM_CVPTR(type, value) \
    ({ \
        type * var = NULL; \
        var = nm_malloc(sizeof(*var)); \
        *var = value; \
        (const void*) var; \
    }) \

#define NM_VPTR(type, value) \
    ({ \
        type * var = NULL; \
        var = nm_malloc(sizeof(*var)); \
        *var = value; \
        (void*) var; \
    }) \

#define NM_PTR(type, value) \
    ({ \
        type * var = NULL; \
        var = nm_malloc(sizeof(*var)); \
        *var = value; \
        (type *) var; \
    }) \

#endif
+2  A: 
Heath Hunnicutt
Nice solution, thank you!
Andrei Ciobanu
I would be curious to know what compiler accepts your second version. I don't think this is C99 as your comment suggests, at least my compiler (gcc 4.3) is not happy with it.
Jens Gustedt
+2  A: 

You can use memcpy to assign a value and then have the pointer returned. The following uses two different versions depending on whether or not your initial value is a primitive type (integer,float, pointers...) or if it is a struct. The value version uses a compound literal (type){ (value) }, so it is only valid in C99.

#include <stdlib.h>
#include <string.h>

static inline
void* memcpy_safe(void* target, void const* source, size_t n) {
  if (target) memcpy(target, source, n);
  return target;
}

#define NM_PTR_RVALUE(type, rvalue)                                     \
  ((type*)memcpy_safe(malloc(sizeof(type)), &(type){ (rvalue) }, sizeof(type)))

#define NM_PTR_LVALUE(type, lvalue)                                     \
  ((type*)memcpy_safe(malloc(sizeof(type)), &(lvalue), sizeof(type)))

typedef struct {
  int a;
} hoi;

hoi H7 = {.a = 7};

int main() {
  int* a = NM_PTR_RVALUE(int, 7);
  hoi* b = NM_PTR_LVALUE(hoi, H7);
}

(Added a NULL check here that uses an inline function, although this wasn't requested originally.)

BTW, in C++ in contrast to C the assignment operator = returns an lvalue, so for C++ you could probably play games with that.

Jens Gustedt
Isn't it dangerous if malloc returns NULL?
Nyan
sure, but not more dangerous than the original version as presented in the question :-)
Jens Gustedt
Thanks for the solution.
Andrei Ciobanu