是否可以重写以下代码,以便符合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
答案 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 ++,你可能会用它来玩游戏。