1

I'm new to programming and to C, and I just learned about structs. I'm trying to use them to make an array which can change size as required (so, if the array gets full, it creates a new array double the size, copies the old array into the new one and deletes the old one). All I've done so far is create the struct and the functions for setting it up, and already I'm having problems. The main problem is that, sometimes when I run it it does exactly what I expect it to, which is create the struct, return a pointer to said struct, and then print all elements of the contained array. Other times when I run it, it does nothing at all! I don't get how it can work sometimes, and sometimes not! Obviously i'm doing something really wrong, but I can't work out what. Here is the code:

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

typedef struct {
    int cap;
    int used;
    void (*cpy) (int *, const int *, int);
    //void (*append) (int);
    int array[];
} dynArray;

dynArray * new_dynArray(int *, int);
void copy(int *, const int *, int);

int main(void) {
    int start_arr[] = {1,2,3,4,5,6};
    // create new dynArray, pass start array and number of elemnts
    dynArray *arr = new_dynArray(start_arr, \
                sizeof(start_arr) / sizeof(start_arr[0]));
    // print all elements of dynArray
    for (int i=0; i<(arr->used); i++) {
        printf("%d, %d\n", arr->array[i], i);
    }
    free(arr);
    return 0;

}

dynArray * new_dynArray(int init_arr[], int size) {
    //printf("%d", size);
    // if number of elements >= 4 then dynArray size is double, else 8
    int init_cap = (size >= 4) ? 2 * size : 8;
    // create pointer with enough space for struct and the actual array
    dynArray *arr = (dynArray *) malloc(sizeof(dynArray) + init_cap );
    arr->cap = init_cap;
    arr->used = size;
    // assign address of funciton copy to arr->cpy
    arr->cpy = copy;
    // call the function, to copy init_arr to arr->array
    arr->cpy(arr->array, init_arr, size);
    return arr;
}

void copy(int dest[], const int src[], int src_size) {
    // just copy initial array to new array
    int i;
    memcpy(dest, src, src_size*sizeof(int));
    /*
    for (i=0; i<src_size; i++) {
        dest[i] = src[i];
        printf("%d\n", dest[i]);
    }*/
}

So I call init_dynArray, sending a normal array and the number of elements in the array. init_dynArray uses malloc to create space in memory for the struct + the inintal size of the array, set up everything in the struct and copy the array, and then return a pointer to it. I don't get how it can only work some of the time. Hope yuo guys can help, thanks!

1 Answers1

1

The problem in your code is on this line:

dynArray *arr = (dynArray *) malloc(sizeof(dynArray) + init_cap );

You need to multiply init_cap by sizeof(int)

dynArray *arr = (dynArray *) malloc(sizeof(dynArray) + sizeof(int)*init_cap );

You should also use size_t for the init_cap's type.

Note: Storing a pointer to the copying function inside the struct would be useful if your dynamic array consisted of opaque elements that require non-trivial copying. Since copying ints can be accomplished with a simple memcpy, there is no need to store a function pointer in dynArray.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Ahh, I see now, thanks! But why before did sometimes work and sometimes fail? – box04057934 Nov 03 '18 at 12:24
  • @box04057934 Because when you fail to allocate enough memory and start writing past the end of your array it's undefined behavior. It gives an appearance of working, but the program is still invalid. – Sergey Kalinichenko Nov 03 '18 at 12:33
  • Right, ok. Thanks for your help. I'd upvote your answer, but I don't have enough reputation. I've accepted it though, thanks again! – box04057934 Nov 03 '18 at 12:40