returning pointer to pointer array of a struct

2019-08-08 17:12发布

问题:

I am working on a C program that holds an array of pointer to structs. First the struct looks like this:

typedef struct
{
    int ID;
    char Name [20];
} rec;

Then I have a function that creates 1 of these structs:

struct rec* addEntry(){
    rec *temp;
    temp = malloc(sizeof(rec));
    printf("Please give me an ID number\n");
    scanf("%d", &temp->ID);

    printf("Now give me a name, maximum size for this is 20 characters\n");
    scanf("%s", &temp->Name);
    return temp;
}

Now this function works fine, it creates the struct and returns the pointer towards that struct I then have another function that creates a pointer array and fills it with pointers towards the structs:

struct rec* returnPointerToPointerArray()
{
    rec *pointerArray[2];
    pointerArray[0] = addEntry();
    pointerArray[1] = addEntry();
    printf("ID in main : %d\n", pointerArray[0]->ID);
    printf("Name in main : %s\n", pointerArray[0]->Name);
    printf("ID in main : %d\n", pointerArray[1]->ID);
    printf("Name in main : %s\n", pointerArray[1]->Name);
    pointerArray = malloc(sizeof(rec*)*2);
    return pointerArray;
}

For checking what happens I print the values that are stored at the places in the pointer array. At this point the values in the pointer array are correct.

However now I need to malloc room for this pointerArray and return a pointer to this pointer array, and that is where I get stuck.

The malloc line gives me an error:

error: incompatible types when assigning to type 'struct rec *[(sizetype)(size)]' from type 'void *'

Now to clarify I cannot use a linked list, I have to use an array of pointers instead. To add in my main loop I have another error in the following bit of code:

rec *pointerArray[2];
pointerArray = returnPointerToPointerArray(2);
printf("ID in main : %d\n", pointerArray[0]->ID);
printf("Name in main : %s\n", pointerArray[0]->Name);

This gives me the following error:

error: incompatible types when assigning to type 'struct rec *[2]' from type 'struct rec *'

Any help is more then welcome.

Thanks in advance, Ylva

回答1:

This code doesn't make sense:

struct rec* returnPointerToPointerArray()
{
    rec *pointerArray[2];
    pointerArray[0] = addEntry();
    pointerArray[1] = addEntry();
    ...
    pointerArray = malloc(sizeof(rec*)*2);
    return pointerArray;
}

you're defining a stack array of pointers and assigning heap addresses for struct rec objects to them and afterwards trying to assign a heap-based array of two pointers to the address of the stack one. It will never compile.

Since your function is designed to return a pointer to an object of rec type (which will be the first of the two structures in the array I guess), you should first allocate on the heap the space for the two pointers (and thus use a double pointer) and then populate it/return it:

struct rec** returnPointerToPointerArray()
{
    rec **pointerArray;
    pointerArray = malloc(sizeof(rec*)*2); // Allocates 2 pointers
    pointerArray[0] = addEntry();
    pointerArray[1] = addEntry();
    ...
    return pointerArray;
}

Live Example

You should also free the allocated memory when you're done.



回答2:

two problems here i identified:

First, you return before you copy the result to pointerArray.

pointerArray = malloc(sizeof(rec*)*2);
return pointerArray;

my suggestion is

struct rec** returnPointerToPointerArray()
{
    rec *pointerArray[2];
    pointerArray[0] = addEntry();
    pointerArray[1] = addEntry();
    printf("ID in main : %d\n", pointerArray[0]->ID);
    printf("Name in main : %s\n", pointerArray[0]->Name);
    printf("ID in main : %d\n", pointerArray[1]->ID);
    printf("Name in main : %s\n", pointerArray[1]->Name);
    rec **pointerArray2 = malloc(sizeof pointerArray);
    pointerArray2[0] = pointerArray[0];
    pointerArray2[1] = pointerArray[1];
    return pointerArray2;
}

notice that i have changed the variable name. you did make some other mistakes in your code.

Second,

rec *pointerArray[2];

is an array of pointer. the way to declare it is simply:

rec **pointerArray;

btw,

pointerArray = returnPointerToPointerArray(2);

this line should make the usage and declaration mismatch.

UPDATE:

found some error in my answer. you are returning an array of pointers.



回答3:

typedef struct
{
    int ID;
    char Name [20];
} rec;

struct rec* returnPointerToPointerArray()
{
    rec *pointerArray[2];
    pointerArray[0] = addEntry();
    pointerArray[1] = addEntry();
    ...
    return pointerArray;
}

The return type is wrong for two reasons. The function returns a rec *, while it is declared to return a pointer to an undefined struct rec *. The type struct rec is not the same as the typedef rec!

Secondly, you should return a pointer to pointer to rec. When you return the array, the array name is converted to a pointer to its first element, which itself is a pointer.

Also, you have declared pointerArray as an actual array. You can not assign a new value to an array, and you can not return a pointer to a local variable. The lifetime of pointerArray ends when execution leaves this function, so a pointer to it will be entirely useless. Using such a pointer results in undefined behaviour.

You need to first allocate dynamic memory for the array, populate the array, and then return it:

rec** returnPointerToPointerArray()
{
  rec **pA = malloc (2 * sizeof *pA);
  if (pA) {
    pA[0] = addEntry();
    pA[1] = addEntry();
    if (pA[0]) {
      printf("ID in main : %d\n", pA[0]->ID);
      printf("Name in main : %s\n", pA[0]->Name);
    }
    if (pA[1]) {
      printf("ID in main : %d\n", pA[1]->ID);
      printf("Name in main : %s\n", pA[1]->Name);
    }
  }
  return pA;
}

Same problem here:

rec *pointerArray[2];
pointerArray = returnPointerToPointerArray(2);
printf("ID in main : %d\n", pointerArray[0]->ID);
printf("Name in main : %s\n", pointerArray[0]->Name);

You can not assign a new value to an array. You need to define pointerArray as a pointer to pointer:

rec **pointerArray;
pointerArray = returnPointerToPointerArray(/*2*/);