有没有一种很好的方法可以将 C99 中的指定初始化程序与 a 的结果结合起来malloc
?
以下似乎有不必要的重复:
typedef struct {
int a, b, c;
} Type;
Type *t = malloc(sizeof *t);
*t = (Type) {
.a = 2,
.b = 3,
.c = 5,
};
可以从上面的代码中删除Type
, 和的使用吗?*t
有没有一种很好的方法可以将 C99 中的指定初始化程序与 a 的结果结合起来malloc
?
以下似乎有不必要的重复:
typedef struct {
int a, b, c;
} Type;
Type *t = malloc(sizeof *t);
*t = (Type) {
.a = 2,
.b = 3,
.c = 5,
};
可以从上面的代码中删除Type
, 和的使用吗?*t
既然你问了;) C 中有一个工具可以避免显式重复代码,即宏。也就是说,我看不到至少不重复类型名称的方法。但是在 C++ 中它们也不能,所以 C 至少一样好 :)
我看到的最简单的是
#define DESIGNATE_NEW(T, ...) \
memcpy(malloc(sizeof(T)), \
&(T const){ __VA_ARGS__ }, \
sizeof(T))
这会给
Type *t = DESIGNATE_NEW(Type,
.a = 2,
.b = 3,
.c = 5,
);
这有几个优点。
0
浮点类型或指针表示的体系结构上也是如此。注意:观察const
宏中的 ,如果编译器认为这是相关的,这允许折叠复合文字的多个实例。还有一种方法是有一个变体,其中指示符列表是可选的,请参见下面的 P99。
缺点是memcpy
,我会更高兴分配。其次,在使用结果之前没有检查是否失败malloc
,但是可能会遇到一些奇怪的情况来让代码很好地退出。
在P99中,我采用了稍微不同的方式。我们总是有一个类型的初始化函数,比如
inline
Type* Type_init(Type* t, int a, int b, int c) {
if (t) {
*t = (Type const){ .a = a, .b = b, .c = c };
}
return t;
}
可以通过宏魔术来为a
,b
以及c
是否省略它们提供默认参数。然后你可以简单地使用类似的东西
Type *t = P99_NEW(Type, 1, 2, 3);
在您的应用程序代码中。这更好,因为它避免了在调用malloc
失败时取消引用指针。另一方面,这重新引入了初始化程序的顺序,因此也不完美。
您可以使用可变参数宏。我不会声称这是一个好主意,但它确实有效:
#include <stdlib.h>
#include <stdio.h>
#define CREATE(type, ptr, ...) \
type *ptr = malloc(sizeof *ptr); \
if (ptr) *ptr = (type){__VA_ARGS__}
int main(void)
{
typedef struct {
int a, b, c;
} Type;
CREATE(Type, t, .a = 2, .b = 3, .c = 5);
printf("t->a = %d, t->b = %d, t->c = %d\n", t->a, t->b, t->c);
return 0;
}
请注意,我无法使用通常的do { ... } while (0)
宏定义技巧(它会创建一个新范围,并且t
不可见),因此您必须小心使用它的上下文。
就个人而言,我认为我对不必要的重复更满意。
不,这是使用指定初始化程序的唯一方法。如果没有 (Type){},编译器不知道如何验证内容。