简体   繁体   中英

How to return a pointer struct array from a function in C

Consider you have a function and the function output will be the Head and Tail address of a Linked List (a function for copy a Linked List in another address):

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;
}

I defined an array of struct path and I return it. In the main function an array has been defined:

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

When I run it, I do not have anything in newPath and it is empty.

So, what is the best way to return these addresses and why I do not have it in newPath ?

Also, when I use:

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

I have an error: error: assignment to expression with array type

How to can I pass these two values to the main function?

Whenever you allocate a dynamic memory(using malloc, calloc, realloc), appropriately typecast the return address to the proper data type. Because these functions return void pointer. In the below line you are assigning the void pointer type address to the struct path type pointer.

temp = malloc(sizeof (struct path));

It can be written as:

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

Second thing, you are returning a array of pointer of type "struct path", but you are collecting this return array of pointer value in a regular pointer of type "struct path" in main which is against the C standard. Correct this mistakes and try to run the code.

In Main use array of pointer to collect the return value:

struct path *newPath[2];

newPath = copyPath(path_head, nextNode)

In addition to the comments, your funciton has two primary problems, 1) you leak memory by overwriting the address of the first allocated block of memory; and 2) you attempt to return returnPath which has automatic storage duration declared local to copyPath .

Memory Leak

You leak memory in your function by overwriting the pointer temp before it has been assigned, eg

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

By allocating a second time for temp before you have assigned the original pointer to another variable, you lose the original pointer in temp pointing to the first block of memory allocated. That memory can never be freed by your program from that point forward.

Returning Array with Automatic Storage Declared Local to Function

When I run it, I do not have anything in newPath and it is empty.

struct path *resultPath[2]; declares an array-of-pointers to struct path (two of them). Automatic storage for resultPath is declared local to copyPath within it function stack frame. When copyPath returns, all local variables with automatic storage duration are destroyed (function stack frame memory is released for reuse). This is expressly explained by C11 Standard - §6.2.4 Storage durations of objects

1) An object has a storage duration that determines its lifetime. There are four storage durations: static, thread, automatic , and allocated. Allocated storage is described in 7.22.3 .

2) The lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it. An object exists, has a constant address,33) and retains its last-stored value throughout its lifetime.34) If an object is referred to outside of its lifetime, the behavior is undefined. The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.

6) For such an object that does not have a variable length array type, its lifetime extends from entry into the block with which it is associated until execution of that block ends in any way .

( emphasis ours )

So, what is the best way to return these addresses and why I do not have it in newPath?

In order to return resultPath, you need to allocate storage for it dynamically and return a pointer to it. Objects with allocated storage duration extend for the lifetime of the program or until they are freed.

The easiest way to declare and allocate for an object capable of storing two pointers to struct path is to declare an pointer-to-pointer to struct path , (effectively a dynamic array of pointers), and allocate storage for two pointers, eg

/* 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;

You can now safely return resultPath and storage for resultPath will survive the return eliminating your access of memory that is no longer available. You then access newHead and newTail through newPath[0] and newPath[1] , respectively, in the caller.

You will also need to change the return type for copyPath to stuct path ** , eg

struct path **copyPath(struct path *head)

and update the type in the caller.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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