【问题标题】:Does a pointer in an array of pointer to struct, if set to NULL, allocate memory?如果设置为 NULL,指向结构的指针数组中的指针是否分配内存?
【发布时间】:2015-09-04 11:49:40
【问题描述】:

我是 C 新手,这是我的第一个问题: 对于这个结构:

typedef struct Branch
{
    Tree * thisTree;
    struct Branch  * nodes[];
} Branch;

如果我执行以下操作,它似乎可以正常工作:

Branch branch1;
branch1->nodes[0] = NULL;

即使我没有以这种方式为数组中的指针 nr 0 分配内存:

branch->node[0] = (Branch *) malloc(sizeof(Branch *));

如果我检查此代码:

if ( branch1->nodes[0] == NULL)
    printf("is NULL");

它打印到输出:是NULL

所以我的问题是: 是否为指针分配了内存?

branch1->nodes[0]

因为我有很多结构,如果我用固定数量的指针初始化每个分支,我会得到很多分配的数据(如果我检查 sizeof 函数)。 这种方式:设置为NULL(上图)是一种错误的思维方式吗?

我的问题是指针的内存分配是 4 个字节。所以在数组中没有声明数量的指针,它什么时候为它分配内存? 对不起 我试图让问题保持简单,但我需要通过下一个分支中的结构指针到达一个字符串

这意味着我使用的结构是

typedef struct Branch
{
    Tree * thisTree;
    char *string;
    struct Branch  * nodes[];
} Branch;

如果我不这样做

branch->node[0] = (Branch *) malloc(sizeof(Branch *));

branch->node[0]->String = strdup("text");

我遇到编译器错误。

【问题讨论】:

  • 不要将malloc和朋友的结果投射到C中。
  • 你做到了。 C 不是 Java 或 Python 等。指针不是引用,而是一等对象。使用 valgrind。如果你不这样做,一个简单的比较甚至可能会起作用,你不能依赖 undefined behavior not 来产生正确的结果。
  • @user3079666:阅读standard。强制转换禁止编译器进行类型检查。如果您的返回类型或参数类型与预期不同,编译器不会警告您。因此,在需要时使用强制转换,并且您真的知道自己在做什么。
  • @BlindWhiteLabMouse 你需要非常小心你在这里做什么。你的struct Branch * nodes[]; 很特别,叫做flexible array member。您还没有为此分配任何内存,所以 branch1->nodes[0] 是未定义的行为。
  • @Olaf C++ 解决了 C 中的一些缺陷,其中包括过于宽松的类型系统。某些被视为危险的隐式转换被禁止,其中包括从 void* 到其他指针的转换。我认为推理有效。我通常也会尝试让我的 C 程序成为 C++ 程序。我知道针对该特定演员的反驳论点,但发现它们要么无效,要么认为它们没有超过好处。我爱我的编译器。如果我在没有先声明的情况下使用函数(如 malloc),它会警告我(任何理智的语言首先都不会允许这种危险,另一课)。

标签: c arrays pointers struct


【解决方案1】:

没有。空指针不分配任何内存来将其存储在堆上,因为没有要分配的内容(因此是“null”)。

您的节点数组确实分配了内存来存储空指针本身,但与存储整数、浮点数、结构等空指针数组所需的内存一样多。

【讨论】:

  • 我的问题是指针的内存分配是4字节。所以在数组中没有声明数量的指针,它什么时候为它分配内存?
  • 是的,它必须为指针本身分配内存。这意味着一个由 10 个整数、10 个结构或 10 个双精度组成的数组将分配 40 个字节(4bytes * 10)或 80 个字节(8bytes * 10),分别在 32 位或 64 位操作系统上运行。将这些指针设置为 null 不会分配更多或更少的字节。
  • 这是个问题,有多少?因为在结构中我没有指定数组中指针的数量
  • @BlindWhiteLabMouse 当您没有指定指针的数量时,您(不知不觉地)使用了 C 的一个称为“灵活数组成员”的功能。您需要为 branch->nodes 元素分配内存,并且不能在堆栈上执行此操作。如果你想分配例如10 个节点指针的空间,你需要做Branch *branch1 = malloc(sizeof(Branch) + 10 * sizeof(Branch*))。只有这样你才能访问 branch1->nodes[0]。之后,您可以为branch1->nodes[0]分配内存,在分配该内存时,您需要考虑branch1->nodes[0]中需要多少个节点。
  • @BlindWhiteLabMouse 是的。最好只使用指向指针数组的普通指针。即 struct Branch **nodes; 而不是 struct Branch * nodes[]; ,这使得重新分配 branch->nodes 而不是 branch 本身更容易。或者,如果您不需要直接索引,请将 branch->nodes 设为链表。
【解决方案2】:

本质上,您正在为指针分配内存,并将值 NULL 放在那里,在 C 中通常为 0。但是该值必须放在分配的内存中,在这种情况下分配给指针,所以是的,仍然为指针分配了内存,你只需将它的值设置为零。

然而,如果你写了branch->node = NULL;,你会取消指针,失去对该内存的访问,但这不是删除它的正确方法,因为内存仍然被分配但无法访问,你应该使用free(branch->node); 取消分配内存,以防你想这样做。

关于内存中分配位置的数量,这将由您乘以 sizeof() 函数的时间来定义:

int number = 2; //assume you want two elements
branch->node[0] = (Branch *) malloc(number*sizeof(Branch *));

【讨论】:

    猜你喜欢
    • 2018-05-16
    • 2013-04-18
    • 1970-01-01
    • 2021-12-26
    • 2012-07-16
    • 2015-04-16
    • 2023-03-28
    • 2015-07-04
    • 2021-12-14
    相关资源
    最近更新 更多