代码之家  ›  专栏  ›  技术社区  ›  Andrei Ciobanu

malloc&init-宏

  •  3
  • Andrei Ciobanu  · 技术社区  · 14 年前

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

    当前代码与GCC编译器(U ses a gcc extension 但是这不是标准的。如果我使用-书呆子,我会收到警告。

    #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 回复  |  直到 14 年前
        1
  •  3
  •   Heath Hunnicutt    14 年前

    可以使用 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存储:

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

    使用上述宏的困难在于宏体中没有块范围,因此 var 在块级别是“可见”,每个宏只能在每个块上使用一次。

    编辑:感谢Jens Gustedt赶上,建议的C++宏不起作用。

        2
  •  3
  •   Jens Gustedt    14 年前

    你可以使用 memcpy 指定一个值,然后返回指针。根据初始值是否为基元类型(integer、float、pointers…)或是否为 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);
    }
    

    (在此处添加了一个使用内联函数的空检查,尽管最初并未请求这种检查。)

    BTW,在C++中,与C相比,赋值算子 = 返回一个LValk,所以对于C++,你可以玩这个游戏。