在 C99+ 中结合指定的初始值设定项和 malloc?

标签 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,
};

是否可以从上面的代码中删除 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;
}

通过宏魔法可以为 abc 提供默认参数(如果它们被省略)。然后你可以简单地使用像

Type *t = P99_NEW(Type, 1, 2, 3);

在您的应用程序代码中。这样更好,因为它避免了在调用 malloc 失败时取消引用指针。另一方面,这向初始化程序重新引入了一个顺序,因此也不完美。

关于在 C99+ 中结合指定的初始值设定项和 malloc?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7265583/

相关文章:

c - Malloc 和 Realloc 的关系,当所需空间在内存中不可用时如何处理

c - 生成二维 vla 以段错误结束

c - 如何从cgo中嵌入的C代码调用Go函数

ios - 如何将此 C 库添加到我的 iOS Xcode 4 项目中?

c - 为什么C标准中没有 "recalloc"?

c++ - 如何将此 C 代码行转换为等效的 C++ 代码?

将 void 指针分配给非 void 指针的 C99 警告?

c - 内部推广 : Is the following well-defined?

c++ - Bison 解析器计算器

c++ - 使用不同的 .dll 静态链接二进制文件(导出相同的符号)