【问题标题】:How to initialize all the pointer fields of struct pointer to NULL?如何将结构指针的所有指针字段初始化为NULL?
【发布时间】:2016-01-23 01:08:50
【问题描述】:

我有以下结构:

 struct node {
    int data;
    struct node *next;
};


struct node *n1 = malloc(sizeof(struct node));

我不确定如何将 struct 指针的所有指针字段初始化为 NULL 而不会导致任何内存泄漏的可能性?

【问题讨论】:

  • 使用calloc 代替malloc
  • n1->next = NULL; 有什么问题?
  • @WeatherVane:这将适用于当前的处理器,但它并不完全正确。
  • 如果你不喜欢 calloc,你可以在你的 malloc 调用之后加上一个 memset,这将完成同样的事情。
  • @WeatherVane:这是一个棘手的问题:它具有 0 的值,因为 NULL == 0 是真的,但它的表示可能不是所有位为零我>。我不知道有哪个 CPU 没有,但标准允许。

标签: c pointers struct


【解决方案1】:

使用malloc分配后需要初始化结构的成员:

struct node {
    int data;
    struct node *next;
};

struct node *n1 = malloc(sizeof(struct node));
n1->data = 0;
n1->next = NULL;

如果你想用默认值一步初始化你的结构,如果它更大的话会很方便,使用带有这些默认值的静态结构:

struct node def_node = { 0, NULL };

struct node *n1 = malloc(sizeof(struct node));
*n1 = def_node;

或者,您可以使用 C99 语法:

struct node *n1 = malloc(sizeof(struct node));
*n1 = (struct node){ 0, NULL };

正如 Leushenko 所说,您可以将任何结构的初始化器缩短为 { 0 },以将所有成员初始化为适合其类型的零:

struct node *n1 = malloc(sizeof(struct node));
*n1 = (struct node){ 0 };

【讨论】:

  • 我正在寻找一种使整个 n1 为 NULL 的方法。例如:n1= {0,NULL};我不想逐个变量。我想一次将所有 n1 设置为 NULL。
  • 这样做的好处是,您在用于初始化值的结构中遗漏的任何字段都将自动设置为该类型的适当零值,因此这是非常可维护的:只需编写一个字段(不能有空文字),其他人会照顾自己。
【解决方案2】:

您有四个选择:

1) 手动设置指针,例如node-> next = NULL;

2) 分配内存时使用calloc() 将其清零

3) 分配内存后,使用memset() 将其清零。

...或者...

4) 在您真正需要使用该结构之前,不要担心显式初始化。设计您的程序,确保在尝试读取之前分配任何指针。

仅供参考,这是 C++ 或 C# 等面向对象语言中“构造函数”的主要目的之一:初始化 "class invariants"

PS:

5) 我忘记了 Leushenko 提到的 C99 结构初始化:

what is the difference between struct {0} and memset 0

struct A
{
    int x;
    int y;
};
...
A a = {0};

非常优于任何一个 calloc() 或memset()。

它也适用于除了“0”之外的其他个初始化值:

C99 标准 6.7.8.21

如果大括号括起来的列表中的初始值设定项比那里少 是聚合的元素或成员,或 用于初始化已知大小的数组的字符串文字 是数组中的元素,聚合的其余部分应为 隐式初始化与具有静态存储的对象相同 持续时间。

【讨论】:

  • 有人会来这里说 calloc()memset() 不能保证将指针设置为 NULL,这在技术上是正确的,但对他们来说,我先发制人地说,它没有的系统'不工作是如此的罕见,以至于我们根本不关心它们。
  • @Dietrich Epp:你完全正确。这些链接进一步解释:c-faq.com/nullstackoverflow.com/questions/9894013/is-null-always-zero-in-c。你也是正确的, calloc() 和 memset() 在几乎所有可以想象的情况下都可以。一个不会使用它们的主要原因是“性能”——无论是否实际需要分配内存的(微不足道的!)开销。
  • @DietrichEpp:我已经在上面的 cmets 中做过,但同意这是一个有争议的问题。感谢 paulsm4 的链接。
  • 不使用它们的更好理由是,当语言提供完成相同工作的原始内置函数时,使用 void * 之上的函数是不优雅的。对于非数组,确实没有理由使用calloc
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-19
  • 1970-01-01
相关资源
最近更新 更多