是否有一种很好的方法可以将C99中的指定初始值设定项与malloc
的结果相结合?
以下似乎有不必要的重复:
typedef struct {
int a, b, c;
} Type;
Type *t = malloc(sizeof *t);
*t = (Type) {
.a = 2,
.b = 3,
.c = 5,
};
可以从上面的代码中删除Type
和*t
吗?
答案 0 :(得分:5)
因为你问过;)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
的调用失败时对指针进行dereferrencing。另一方面,这会重新引入初始化程序的顺序,因此也不完美。
答案 1 :(得分:2)
您可以使用可变参数宏。我不会声称这是一个好主意,但它确实有效:
#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
不可见),所以你必须是小心你使用它的上下文。
就个人而言,我认为我对不必要的重复感到高兴。
答案 2 :(得分:1)
不,这是使用指定初始值设定项的唯一方法。如果没有(Type){},编译器就不知道如何验证内容。