1

Let's say I have to create an array of structs that is allocated on the heap and return a pointer that points to this array of structs.

typedef struct Pair {
    int x;
    int y;
} Pair;

Pair** foo(int n, int m, int length)
{
    Pair* arr = malloc(sizeof(*arr) * length);

    for (int i = 0; i < length; ++i) {
        arr[i].x = n++;
        arr[i].y = m++;
    }

    return &arr;
}

When I compile a program containing this function, it warns me that I am returning the address of a local variable. I assume this is because the pointer is initialised within the function (i.e. on the stack), therefore it counts as a local variable.

When I compile it, ignoring this warning, and run it anyway, the program crashes when the returned pointer is accessed.

I have tried allocating the pointer dynamically:

Pair** ptr = malloc(sizeof(**ptr));
ptr = &arr;
...
return ptr;

but the program still crashes when this pointer is accessed. How can I create this array within a function and return a pointer to this array so that it can be safely accessed?

1
  • 2
    Do you need an array of structures, or an array of pointers to structures? Commented Jul 26, 2018 at 2:10

4 Answers 4

4

This array is initialized on the stack but the pointer (arr) is a local variable, so the caller, main, cannot access it. You do not need to use the address of the pointer. You can access the array with the pointer itself.

Pair* foo(int n, int m, int length)
{
    Pair* arr = malloc(sizeof(*arr) * length);

    for (int i = 0; i < length; ++i) {
        arr[i].x = n++;
        arr[i].y = m++;
    }

    return arr;
}
Sign up to request clarification or add additional context in comments.

Comments

1

If you want an array of structs, the code:

#include <stdio.h>
#include <stdlib.h>

typedef struct {
    int x;
    int y;
} Pair;

static Pair* foo(int n, int m, int length)   {
    Pair* arr = malloc(sizeof(*arr) * length);
    for (int i = 0; i < length; ++i) {
        arr[i].x = n++;
        arr[i].y = m++;
    }
    return arr;
}

int main(void) {
    Pair *z = foo(111, 222, 3);
    for (int i = 0; i < 3; ++i) 
        printf("z[%d]= { %d, %d }\n", i, z[i].x, z[i].y);
    free(z);
    return 0;
}

gives the output:

z[0]= { 111, 222 }
z[1]= { 112, 223 }
z[2]= { 113, 224 }

Comments

-1

If you want an pointer to an array of structs, you can change your function signature from Pair** to be Pair*.


If you still want an pointer to an array of pointers, then allocate memory for a Pair struct for each index of arr.

for(int i = 0; i < length; ++i){
    arr[i] = malloc(sizeof(Pair));
    ...
}

Instead of returning &arr, you can declare arr as

Pair** arr = malloc(sizeof(Pair*) * length);

7 Comments

@GabrielSaul This returns an array of pointers, not an array of structures. Is that really what you want?
If you do this, you have to change arr[i].x = n++; to arr[i]->x = n++; since arr[i] is a pointer.
(a) The first statement is wrong; OP’s Pair* arr = malloc(sizeof(*arr) * length); allocates memory for length objects of type Pair. (b) OP does not need to create an array of pointers. Their declaration of foo as returning Pair ** is a mistake; they only need to return a Pair *, and they only need to allocate an array of Pair objects. They do not need, according to the question as stated, to create an array of pointers to Pair objects.
It is not likely OP wants an array of pointers. They refer to an array of struct. Most likely they want a pointer to the first struct of an allocated array. Possibly, but less likely, they want a pointer to such a pointer. Even less likely do they want a pointer to the first element of an array of pointers to struct.
@Miket25: What you would place your money on is not of use to anybody in determining OP’s desires. The text of their request supplies information; they request “I have to … return a pointer that points to this array of structs.” Additionally, a person asking a question at this level is a novice; they are at the stage where students learn to use pointers for the first time, and the exercises they are given are to allocate space for an array and to return a pointer to the space.
|
-1

Because arr is a local variable, it will be free when foo end. So you don't have access for arr after. To solve this you should declare array pointer in heap:

     Pair** foo(int n, int m, int length)
     {
           Pair ** arr = (Pair**)malloc(sizeof(Pair*));
           *arr = malloc(sizeof(Pair) * length);

           for (int i = 0; i < length; ++i) {
               (*arr)[i].x = n++;
               (*arr)[i].y = m++;
           }

            return arr;
       }

5 Comments

@JosephQuinsey: Either Pair **arr = malloc(sizeof *arr); *arr = malloc(sizeof **arr * length); is correct or Pair *arr = malloc(sizeof *arr * length); is correct. Deleting the second malloc and putting length in the first without changing it from Pair ** to Pair * is incorrect. Likely the latter is desired; OP probably does not need the former.
Can you explain why? I dont understand
@LinhNguyenHuy: Deleting the second malloc and putting length in the first produces Pair **arr = (Pair*)malloc(sizeof(Pair*)*length);, which allocates space for length pointers to struct. But the question does not request an array of pointers. It requests an array of structures.
Additionally, it leaves the type mismatch; the cast is to Pair *, but the object being initialized has type Pair **.
Ya. But I think I just modify the cast to (Pair**). The function requests a pointer of array so I return a pointer of array =))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.