如何从C中的函数返回指针结构数组

时间:2018-03-28 04:52:48

标签: c arrays function linked-list

考虑你有一个函数,函数输出将是一个Linked List的头部和尾部地址(一个用于复制另一个地址中的Linked List的函数):

struct path *copyPath(struct path *head) {

  struct path *temp = malloc(sizeof (struct path));  

  // array of newHead and newTail
  struct path *resultPath[2];

  struct path *newHead = NULL;
  struct path *newTail = NULL;    

  while (head != NULL) {
      temp = malloc(sizeof (struct path));
      if (newHead == NULL) {
          // Add a new node to the first of list and save newHead as the beginning of the list
      } else {            
          // Add the other nodes and save the last node address as newTail
      }
      head = head -> next;
  }      

  resultPath[0] = newHead;
  resultPath[1] = newTail;        

  return resultPath;
}

我定义了一个struct path的数组,然后我将其返回。在main函数中定义了一个数组:

struct path *newPath;
newPath = copyPath(path_head, nextNode);

当我运行它时,我在newPath中没有任何内容,它是空的。

那么,返回这些地址的最佳方法是什么?为什么我没有newPath

另外,当我使用:

struct path *newPath[2];
newPath = copyPath(path_head, nextNode);

我有一个错误:error: assignment to expression with array type

如何将这两个值传递给main函数?

2 个答案:

答案 0 :(得分:1)

每当您分配动态内存(使用malloc,calloc,realloc)时,请将返回地址适当地转换为正确的数据类型。因为这些函数返回void指针。在下面的行中,您将void指针类型地址分配给结构路径类型指针。

temp = malloc(sizeof(struct path));

可以写成:

temp =(struct path *)malloc(sizeof(struct path));

第二件事,你正在返回一个类型为" struct path"的指针数组,但是你正在以#34; struct path"类型的常规指针收集这个指针值的返回数组。在主要是违反C标准。纠正这个错误并尝试运行代码。

在主要使用指针数组中收集返回值:

struct path * newPath [2];

newPath = copyPath(path_head,nextNode)

答案 1 :(得分:1)

除了注释之外,你的功能有两个主要问题:1)你通过覆盖第一个分配的内存块的地址来泄漏内存; 2)您尝试将returnPath的自动存储持续时间返回到copyPath

内存泄漏

通过在分配指针temp之前覆盖它来泄漏函数中的内存,例如。

struct path *temp = malloc(sizeof (struct path));  
...
while (head != NULL) {
    temp = malloc(sizeof (struct path));

通过在将原始指针指定给另一个变量之前为temp分配第二次,您将丢失指向所分配的第一个内存块的temp中的原始指针。从那时起,你的程序永远无法释放那段记忆。

使用自动存储返回数组声明本地功能

  

当我运行它时,我在newPath中没有任何内容,它是空的。

struct path *resultPath[2];声明指向struct path 的指针数组(其中两个)。 resultPath的自动存储在其功能堆栈帧中被声明为copyPath的本地存储。当copyPath返回时,将销毁具有自动存储持续时间的所有局部变量(释放函数堆栈帧存储器以供重用)。 C11 Standard - §6.2.4 Storage durations of objects

明确解释了这一点

1)对象具有确定其生命周期的存储持续时间。有四个存储持续时间:静态,线程,自动和已分配。分配的存储在7.22.3中描述。

2)对象的生命周期是程序执行的一部分,在此期间保证为其保留存储。存在一个对象,具有一个常量地址,33)并在其整个生命周期内保留其最后存储的值.34)如果一个对象在其生命周期之外被引用,则该行为是未定义的。当指针指向(或刚刚过去)的对象到达其生命周期的末尾时,指针变得不确定。

6)对于没有可变长度数组类型的对象,其生命周期从entry进入与其关联的块,直到该块的执行结束为​​止方式

强调我们的

  

那么,返回这些地址的最佳方式是什么?为什么我在newPath中没有它?

为了返回resultPath,您需要动态地为其分配存储并返回指向它的指针。具有分配的存储持续时间的对象会延长程序的生命周期或直到它们被释放。

为能够存储两个指针struct path的对象声明和分配的最简单方法是声明一个指向结构路径的指针,(实际上是一个动态数组指针),并为两个指针分配存储空间,例如

/* allocate & validate 2 pointers to struct path */
struct path **resultPath = malloc (sizeof *resultPath * 2);
if (!resultPath) {        /* always validate all memory allocations */
    perror ("malloc resultPath failed.");
    return NULL;
}
...
resultPath[0] = newHead;  /* newHead & newTail must point to allocated memory */
resultPath[1] = newTail;        

return resultPath;

您现在可以安全地return resultPath并且resultPath的存储将在返回后继续存在,从而消除您对不再可用的内存的访问。然后,您可以分别在来电者中访问newHeadnewTailnewPath[0]newPath[1]

您还需要将copyPath的返回类型更改为stuct path **,例如

struct path **copyPath(struct path *head)

并更新来电者的类型。