I saw quite a few posts about making a dynamic array so I tried making my own for learning purposes.
Here it is:
#ifndef VECTOR_H #define VECTOR_H #include <stdlib.h> #include <stdbool.h> #include <string.h> #ifndef VECTOR_RESERVE_SIZE #define VECTOR_RESERVE_SIZE 4 #endif //Declaration typedef struct { int size_of_each; int reserved; int used; void* data; } vector_t; bool vector_init(vector_t *, int); void vector_append(vector_t *, void *); void* vector_get(vector_t *, int ); void vector_set(vector_t *, int, void *); void vector_free(vector_t *); //Implementation bool vector_init(vector_t *p, int s) { p->size_of_each = s; p->reserved = VECTOR_RESERVE_SIZE; p->used = 0; p->data = malloc(VECTOR_RESERVE_SIZE * p->size_of_each); if (p->data != NULL) { return false; } else { return true; } } void vector_append(vector_t *p, void *d) { if (p->used == p->reserved) { p->data = realloc(p->data, VECTOR_RESERVE_SIZE); //printf("reallocated \n"); p->reserved += VECTOR_RESERVE_SIZE; } memcpy((void*)((char*)p->data + p->size_of_each * p->used), // copy to back of the vector d, p->size_of_each); p->used += 1; } void* vector_get(vector_t *p, int i) { if (!(i > p->used)) { return (void*)((char*)p->data + p->size_of_each * i); } else { return NULL; } } void vector_set(vector_t *p, int i, void *d) { if (!(i > p->used)) { memcpy((void*)((char*)p->data + p->size_of_each * i), d, p->size_of_each); } } void vector_free(vector_t *p) { free(p->data); } #endif
Here is an example of its usage:
#include <stdio.h> #define VECTOR_RESERVE_SIZE 3 #include "vector.h" int main() { int a = 321; int b = 45; int c = 21; int d = 31; int e = 71; vector_t v; vector_init(&v, sizeof (int)); vector_append(&v, &a); vector_append(&v, &b); vector_append(&v, &c); vector_append(&v, &d); vector_append(&v, &e); printf("1st element is %d \n", *(int*)vector_get(&v, 0)); printf("2nd element is %d \n", *(int*)vector_get(&v, 1)); printf("3th element is %d \n", *(int*)vector_get(&v, 2)); printf("4th element is %d \n", *(int*)vector_get(&v, 3)); printf("5th element is %d \n\n", *(int*)vector_get(&v, 4)); vector_set(&v, 4, &a); printf("4th element after setting is %d \n\n", *(int*)vector_get(&v, 4)); //contiguous printf("size of int is: %d \n", sizeof (int)); printf("address of 1st element: %p \n", vector_get(&v, 0)); printf("address of 2nd element: %p \n", vector_get(&v, 1)); printf("address of 3rd element: %p \n", vector_get(&v, 2)); printf("address of 4th element: %p \n", vector_get(&v, 3)); printf("address of 5th element: %p \n", vector_get(&v, 4)); vector_free(&v); }
I've written some C++ before and this was one of my first few projects in C.
I'd like to know overall how good my code is and whether I'm using good practices / conventions.
Edit:
this: p->data = realloc(p->data, VECTOR_RESERVE_SIZE);
should be this: p->data = realloc(p->data, (p->reserved + VECTOR_RSERVE_SIZE) * P->size_of_each);
Edit: Maybe it's too late but, if people are still reviewing this I would really like to know how does this approach compare to std::vector.