0

For an university assignment I'm trying to implement an array of structures which is contained in another structure. The array has to be dynamic. Now, my understanding was that in order to do so I had to create three separate allocations.

struct_array* create_struct_array (size_t size) {
    struct_array* sa = (struct_array*) malloc(sizeof(struct_array));
    sa->pt = (my_struct**) malloc(size * sizeof(my_struct));
    for(int i = 0; i < size; i++)
        sa->pt[i] = (my_struct*) malloc(sizeof(my_struct));
    sa->size = size;
    return sa; 
};

The first is for the memory containing the struct_array variable, and the instruction seems to work just fine. The second is for the total space occupied by the array (pt), based on the number of items it will have. Here comes the trouble. The line, instead of allocating the exact memory I'd like to, always creates x slots where x is equal to the numbers of elements of my_struct. So since my_struct has four elements right now, it will create four slots, no less, no more. If I were to remove the element d from my_struct, it would create three instead of four. The third allocations is specific to every single element of the array and it validates the address. This too seems to work just fine. When I call the function on an array with size zero of course the loop won't start at all, when the array has to contain one single element it will validate the first address, with size == 2 it will validate 2 members and so on. To further clarify, here are some images I took of the situation in the debug window

This is just after the first allocation

This is after the SECOND allocation

And finally, this is after the third

I've banged my head on the wall all day long, but I couldn't find a solution. I also searched among a certain number of other solutions. One in particular was also the first thing that helped me write this code in the first place. Here it is Pointer to array of pointers to structure. Finally, here's the complete demo code so if anyone will be so kind to help me he can just try to run this. I'm running it on the CLion IDE with the C90 standard.

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

typedef struct my_struct {
    int     a;
    int     b;
    int     d;
    char    c;
} my_struct;

typedef struct struct_array {
    my_struct** pt; // This is intended to be an array of pointers to my struct
    size_t size;
} struct_array;

struct_array* create_struct_array (size_t size) {
    struct_array* sa = (struct_array*) malloc(sizeof(struct_array));
    sa->pt = (my_struct**) malloc(size * sizeof(my_struct));
    for(int i = 0; i < size; i++)
        sa->pt[i] = (my_struct*) malloc(sizeof(my_struct));
    sa->size = size;
    return sa;
};

void free_struct_array (struct_array* sa) {
    for (int i = 0; i < sa->size; i++)
        free(sa->pt[i]);
    free(sa->pt);
    free(sa);
}

void copy_element(struct_array* sa, my_struct e, int index) {
    sa->pt[index]->a = e.a;
    sa->pt[index]->b = e.b;
    sa->pt[index]->d = e.d;
    sa->pt[index]->c = e.c;
}

void copy_array (struct_array* copy, struct_array* original) {
    for (int i = 0; i < original->size; i++)
    {
        copy_element(copy, *original->pt[i], i);
    }
}

struct_array* add_to_struct_array (struct_array* sa, my_struct new_element) {
    struct_array* new = create_struct_array(sa->size + 1);
    copy_array(new, sa);
    copy_element(new, new_element, new->size - 1);
    free_struct_array(sa);
    return new;
}

int main() {
    struct_array* sa = create_struct_array(0);
    for (int i = 0; i < 5; i++)
    {
        my_struct e = {i, i * 2, i*10, (char) i+65};
        sa = add_to_struct_array(sa, e);
    }
    for (int i = 0; i < 5; i++)
    {
        printf("sa->pt[%i]->a = %i\n", i, sa->pt[i]->a);
        printf("sa->pt[%i]->b = %i\n", i, sa->pt[i]->b);
        printf("sa->pt[%i]->d = %i\n", i, sa->pt[i]->d);
        printf("sa->pt[%i]->c = %c\n", i, sa->pt[i]->c);
    }
    free_struct_array(sa);
    return 0;
}
  • 1
    *instead of allocating the exact memory I'd like to. always creates x slots*. After reading the whole thing a few times I still could not understand what you are asking. You tell it to allocate `size` elements and it allocates exactly that many elements. So what is the problem? Can you please clearly and concisely give the exact expected behaviour vs actual behaviour? – kaylum Dec 11 '20 at 21:29
  • If your struct contains a pointer to ... I would not say "it contains an array of ...", containing an array is something like the following: struct foo { int arr[100]; }; And note that if it were the following: struct foo { int count; int arr[]; }; it would still be possible to allocate as a single block, just have to claculate the space needed by the array in addition to the containing struct. Though that only works if the unsized array is the last member of the struct and also doesn't work if there are multiple levels of nesting. – SoronelHaetir Dec 11 '20 at 21:45
  • I don't understand what's your question. You don't have an "array of struct" as stated in the title of the question but an "array of pointers to struct". The allocation for the array of pointers `sa->pt = (my_struct**) malloc(size * sizeof(my_struct));` uses the wrong size. It should be changed to `sa->pt = malloc(size * sizeof(my_struct*));`. Do you want an array of structures instead of an array of pointers to (dynamically allocated) structures? If you want to increase the array you could use `realloc` for the array of pointers and `malloc` for the additional structure element(s). – Bodo Dec 11 '20 at 21:48

0 Answers0