有没有一种很好的方法可以将 C99 中的指定初始化程序与 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
的标准表示。 - 除了 Keith 的版本之外,它是可接受的“编码风格”,因为它只是一个看起来像初始化的表达式,任何人都应该立即直观地捕捉第二个代码片段集应该做什么。
注意:观察宏中的 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
失败时取消引用指针。另一方面,这向初始化程序重新引入了一个顺序,因此也不完美。
关于在 C99+ 中结合指定的初始值设定项和 malloc?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7265583/