Malloc& Init - MACRO

时间:2010-06-20 17:31:17

标签: c standards macros gnu

是否可以重写以下代码,以便符合ISO C标准? 以下宏正在做一个malloc& init为给定的类型和值。

当前代码适用于gcc编译器(u ses a gcc extension),但它不是标准的。如果我使用-pedantic,我会收到警告。

#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 个答案:

答案 0 :(得分:3)

这可以使用comma operator来完成,但在标准C中,您将无法将变量声明为表达式的一部分,因此您必须传递var'的名称替换宏:

// C - comma operator but not able to declare the storage during the
// expression.
#define NM_PTR(type, var, value) \
    (var = nm_malloc(sizeof(*var)), \
    *var = value, \
    (type * var))

在某些编译器和C ++中,您可以按如下方式声明var in-line的存储:

// C99 and C++
#define NM_PTR(type, value) \
    (type * var = nm_malloc(sizeof(*var)), \
    *var = value, \
    (type * var))

使用上面的宏的困难在于宏体中没有块范围,因此var的定义在块级别是“可见的”,每个宏都可以每块仅使用一次。

编辑:感谢Jens Gustedt发现建议的C ++宏不起作用。

答案 1 :(得分:3)

您可以使用memcpy分配值,然后返回指针。以下使用两个不同的版本,具体取决于您的初始值是基本类型(整数,浮点数,指针...)还是struct。值版本使用复合文字(type){ (value) },因此它仅在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);
}

(在这里添加了一个使用内联函数的NULL检查,尽管最初没有请求。)

BT,在C ++中,与C相比,赋值运算符=返回一个左值,因此对于C ++,你可能会用它来玩游戏。