9

有没有一种很好的方法可以将 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

4

3 回答 3

6

既然你问了;) 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失败时取消引用指针。另一方面,这重新引入了初始化程序的顺序,因此也不完美。

于 2011-09-22T06:31:20.153 回答
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不可见),因此您必须小心使用它的上下文。

就个人而言,我认为我对不必要的重复更满意。

于 2011-09-01T03:18:59.997 回答
1

不,这是使用指定初始化程序的唯一方法。如果没有 (Type){},编译器不知道如何验证内容。

于 2011-09-01T02:46:25.833 回答