【问题标题】:C - Allocating memory to a pointer to a member in a StructC - 将内存分配给指向结构中成员的指针
【发布时间】:2020-03-09 23:15:05
【问题描述】:

我已经看到了很多其他问题,但是我似乎仍然无法弄清楚如何初始化指向同时也是指针的结构成员的指针。鉴于我指向我的结构的指针(其中包含一个作为指针的成员),我想初始化一个指向该成员指针的指针。

例如,将节点添加到链表时,我所学的示例中给出的参数是 addNode(**head, etc)。我想知道我是否需要为这个指针分配内存以及如果我在下面的代码中做错了如何初始化它。

int row, col;
double val;
char nwln;

sp_tuples_node ** tuplepointer/* = malloc(sizeof(sp_tuples_node *));*/

FILE * inFile = fopen(input_file, "r");
sp_tuples * new_tuples = malloc(sizeof(sp_tuples));
tuplepointer = new_tuples->tuples_head;
fscanf(inFile, "%d %d%c", &row, &col, &nwln);

  //while not eof
  fscanf(inFile, "%d %d %d%c", &row, &col, &val, &nwln);
  addNode(tuplepointer, row, col, val);
  return new_tuples;

有问题的行由新行分隔,其余未完成的代码用于调用函数的上下文,应忽略其功能。

感谢您提供有关如何将指针分配给指针成员的任何反馈。

【问题讨论】:

  • 什么是sp_tuples_node?这听起来像是typedef 指向结构的匈牙利符号。我认为在同一个声明 (sp_tuples_node** tuplepointer) 中混合 typedef 和多个指针不是一个好主意,因为目前还不清楚指针间接发生了多少。
  • 我看到大量无效内存的立即使用(malloc 在分配后不会将内存归零,而calloc 会),例如tuplepointer = new_tuples->tuples_head 在new_tuples = malloc(sizeof(sp_tuples)) 之后 -你不应该这样做,智能编译器会给你一个警告。
  • 我尝试寻找有关家庭作业样式格式的标签,但是我找不到一个这不是硬件的答案(只是为了澄清我不是想得到答案)。我无法更改愚蠢的符号(我同意它真的很难阅读)。感谢您指出我的错误,但我会将其添加到我的修复中。对于指向结构中成员的指针,我应该为整个单独的类型分配内存(ex: tuplepointer = calloc(sizeof(tuple_node_struct)
  • 或者我应该初始化一个像(tuple_node_struct ** tuplepointer;)tuplepointer = new_tuples->tuples_head这样的指针

标签: c pointers dynamic-memory-allocation


【解决方案1】:

每当您声明类型 pointer-to-pointer-to type 时,您需要 两次 分配才能使用任何 pointer- to type 通过 pointer-to-pointer-to type 引用(或至少一个指针分配,然后将现有对象分配给每个分配的指针)。

以您的声明为例:

sp_tuples_node **tuplepointer;

(假设std_tuples_node 不是某个类型定义的指针)

你需要做的是:

  • 首先分配一些指针。为什么?你有一个指针到指针。那是一个持有 pointer-to type 地址的单指针。如果要引用类型对象的50,则必须分配50 指针,以便tuplepointer 指向包含50 指向类型sp_tuples_node 的指针的内存块。

例如:

tuplepointer = malloc (50 * sizeof *tuplepointer);    /* allocate 50 pointers */
if (!tuplepointer) {                                  /* validate allocation */
    perror ("malloc-tuplepointer");
    exit (EXIT_FAILURE);
}
  • 其次,您可以为每个sp_tuples_node 分配存储空间,并为分配给上面已分配并分配给tuplepointer 的内存块中的50 指针之一的每个块分配起始地址。

例如:

for (size_t i = 0; i < 50; i++) {
    tuplepointer[i] = malloc (sizeof *tuplepointer[i]);
    if (!tuplepointer[i]) {
        perror ("malloc-tuplepointer[i]");
        exit (EXIT_FAILURE);
    }
}

(注意:如果你总是使用 dereferenced pointer 来为你分配的类型设置 typesize -- 你永远不会得到你的 typesize 错误)

现在您已经为50 指针分配了存储空间,并将起始地址分配给了tuplepointer。您还为50 - sp_tuples_node 分配了存储空间,并且将每个地址的起始地址分配给了分配给tuplepointer 的块中的50 指针之一。您可以使用 array-index 表示法将每个 sp_tuples_node 引用为 tuplepointer[i]。

如果sp_tuples_node 包含另一个指向某个类型的指针作为结构的成员,您现在可以分配一个存储块并将起始地址分配给该指针。假设您有char *str; 作为sp_tuples_node 的成员。然后您可以分配:

size_t len = strlen(somestring);
tuplepointer[i]->str = malloc (len + 1);   /* allocate storage for str, assign to ptr */
/* validate allocation ... */
memcpy (typlepointer[i]->str, somestring, len + 1);

等等等等...您可以根据需要多次执行此操作。您唯一需要保持直截了当的是您是分配指针还是为对象分配存储空间。显然,使用 pointer-to-pointer-to type 您正在分配指针,当您取消引用一次并需要为 pointer-to type 分配时,您正在分配对象的存储。

你如何保持直截了当?

这样想。当您取消引用要分配的类型时——您有什么?

  • 带有 pointer-to-pointer-to type,当取消引用时,您有 pointer-to type(您正在分配指针)
  • 带有一个指向type的指针,当取消引用时你有type(你正在分配一个对象)

最后,您在问题中提到了 linked-list 并提到了addNode(**head, etc)。那是不同的。在这种情况下,您可能在调用者中有(比如main())

node *head;

然后你打电话给:

addNode (&head, etc);

那里的参数类型是 pointer-to-pointer-to head,因为您将 地址 传递回 main() 中的原始指针。 head 本身已经有一个有效的地址,所以你不要为 head 本身分配。

您传递&amp;head,因此函数addNode 接收原始指针的地址,而不是指针的副本。这样,如果您需要为通过head 引用的节点分配存储空间,您可以分配*head = malloc (sizeof **head); 并且在函数返回时head 将指向在addNode() 中分配的新内存块,而无需返回并分配起始新分配的内存块的地址。

让我知道这是否有助于清除它。如果没有,我很乐意再试一次。

【讨论】:

  • 非常感谢您的详细回复,您提供的代码符合您的考虑(尽管我可能必须完全更改代码,具体取决于我的功能是否正确)。正如您在上一节中所说,我正在尝试实现一个与某些数据交互并将其存储为链表的程序,我正在尝试实现我自己的 add、rm 和 find 函数以便更轻松地操作数据.不确定它是否会这样,但你的解释以非常彻底的方式向我解释了这个话题,即使我必须改变它,我也学到了很多!
  • 很高兴它有帮助。祝你的项目好运。您可能会发现 Singly Linked List (node only, no wrapper) 对简单的链表示例很有帮助。通过同时跟踪head 和tail 节点可以获得更高的插入效率,从而无需重复查找下一个插入点。您可能会发现 Singly Linked List of Integers (example) 有指导意义 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-05-16
  • 2014-02-23
  • 1970-01-01
  • 2020-10-30
  • 2013-12-26
  • 2019-03-18
  • 1970-01-01
相关资源
最近更新 更多