box04057934
box04057934

Reputation: 23

inconsistent results for struct with array in c

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!

Upvotes: 1

Views: 106

Answers (1)

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726509

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.

Upvotes: 1

Related Questions