在C99 +中结合使用指定的初始化程序和malloc?

Mat*_*ner 8 c malloc c99 designated-initializer

有没有一种很好的方法来组合来自C99的指定初始化器,结果是malloc

以下似乎有不必要的重复:

typedef struct {
   int a, b, c;
} Type;

Type *t = malloc(sizeof *t);
*t = (Type) {
    .a = 2,
    .b = 3,
    .c = 5,
};
Run Code Online (Sandbox Code Playgroud)

可以使用Type,并*t从上面的代码中删除?

Jen*_*edt 5

因为你问过;)C中有一个工具可以避免显式重复代码,宏.那说我没有办法不重复至少类型的名称.但是在C++中他们也不能,所以C至少同样好:)

我看到的最容易的是

#define DESIGNATE_NEW(T)            \
  memcpy(malloc(sizeof(T)),         \
         &(T const){ __VA_ARGS__ }, \
         sizeof(T))
Run Code Online (Sandbox Code Playgroud)

这会给

Type *t = DESIGNATE_NEW(Type,
    .a = 2,
    .b = 3,
    .c = 5,
);
Run Code Online (Sandbox Code Playgroud)

这有几个优点.

  • 它正确初始化所有成员,即使在具有0for float类型或指针的非标准表示的体系结构上也是如此.
  • 除了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;
}
Run Code Online (Sandbox Code Playgroud)

它通过宏观魔法可制成用于提供默认参数a,b并且c如果他们被省略.然后你可以简单地使用类似的东西

Type *t = P99_NEW(Type, 1, 2, 3);
Run Code Online (Sandbox Code Playgroud)

在您的应用程序代码中 这样做更好,因为它可以避免在调用malloc失败时对指针进行dereferrencing.另一方面,这会重新引入初始化程序的顺序,因此也不完美.