繁体   English   中英

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

[英]How to return a pointer struct array from a function in C

假设您有一个函数,函数输出将是链表的头和尾地址(将链表复制到另一个地址的函数):

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数组,并将其返回。 在主函数中,已定义了一个数组:

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

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

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

temp = malloc(sizeof(结构路径));

它可以写成:

temp =(结构路径*)malloc(sizeof(结构路径));

第二件事,您正在返回类型为“ struct path”的指针数组,但是您正在使用main违反C标准的main类型为“ struct path”的常规指针收集此指针值的返回数组。 更正此错误,然后尝试运行代码。

在Main中使用指针数组来收集返回值:

结构路径* newPath [2];

newPath = copyPath(path_head,nextNode)

除注释外,您的功能还有两个主要问题:1)通过覆盖分配的第一个内存块的地址来泄漏内存; 和2)您尝试返回returnPath ,该方法具有声明为copyPath本地的自动存储持续时间。

内存泄漏

通过在分配指针temp之前覆盖指针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的指针数组 (其中两个)。 在函数堆栈框架中,将copyPath自动存储声明为resultPath的本地存储。 copyPath返回时,具有自动存储持续时间的所有局部变量都将被销毁(释放函数堆栈帧存储器以供重新使用)。 C11标准-§6.2.4对象的存储持续时间明确说明了这一点

1)对象的存储期限决定了其生存期。 有四个存储期限:静态,线程, 自动和已分配。 分配的存储在7.22.3中描述。

2)对象的生存期是程序执行的一部分,在此期间保证为其保留存储空间。 一个对象存在,具有恒定的地址33),并在其整个生命周期中保留其最后存储的值。34) 如果在其生命周期之外引用了一个对象,则该行为是不确定的。 当指针所指向的对象(或刚过去的对象)达到其生命周期的终点时,指针的值将变得不确定。

6)对于这样一个不具有可变长度数组类型的对象,其生存期从进入与之相关联的块开始,直到该块的执行以任何方式结束

强调我们的

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

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

声明和分配能够存储两个指向struct path指针的对象的最简单方法是,声明一个指向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并且return resultPath存储将在返回后resultPath存在,从而消除了对不再可用的内存的访问。 然后,您分别通过调用者中的newPath[0]newPath[1]访问newHeadnewTail

您还需要将copyPath的返回类型copyPathstuct path ** ,例如

struct path **copyPath(struct path *head)

并更新呼叫者中的类型。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM