I really like to make tools prior to starting some assignment, so for the C programming assignments I have prepared dynamic array library. We are restrained to only using C99 standard.
Note that all programming I'm describing below is, as per question title, done for education purposes. This is not production code but code I use to practice programming. And AFAIK specifically the subject I'll be submitting the homeworks to has no external libraries rule anyway.
I will intentionally skip implementation details now, the "library" has following format (interface, if you wish):
typedef struct {
//How many elements are in array
// READ ONLY!!! Do not change
size_t length;
/** all the rest is private, do not touch **/
... omitted for brevity ...
} Array;
/** Creates new empty array. The returned pointer must be
* correctly destroyed using array_destroy.
* Inital size is allowed to be zero
* **/
Array* array_create(size_t elm_size, size_t initalSize);
/**
* Allocate memory so that `count` ENTRIES fits into the array.
* If the array already has enough memory, nothing happens.
*/
void array_reserve(Array* a, size_t count);
/** Expands the array to required size. The value of
* new fields is undefined. There is little reason to use
* this instead of array_push or array_reserve */
void array_expand(Array* a, size_t length);
/**
* Adds an element at the end of the array, realocating memory if necesary **/
void array_push(Array* a, const void* element);
/**
* Sets value at offset in array. This ofset MUST be valid.
* The `element` must be pointer to correct ammount of memory, that is
* the correct type */
void array_set(Array* a, size_t offset, const void* element);
Now this looked nice, but I started using it and it's not very fun. Simple arrays are OK I guess...
int numbers[] = {5,4,3,2,1};
Array* ar = array_create(sizeof(int), 0);
// Oh, one thing that sucks is that you can't add literals
// because you can't provide pointer to them
array_push(ar, numbers+0);
array_push(ar, numbers+1);
...
array_push(ar, numbers+4);
int number;
// This is super cool macro
// Remember this is gcc with -pedantic -Wall -std=c99
AR_FOREACH(number, ar, int) {
printf("Number: %d\n", number);
}
That prints:
Number: 5
Number: 4
Number: 3
Number: 2
Number: 1
But it really gets complicated with multidimensional arrays. I want to use my "library" for matrices. Now, just to make Array
of Array
s and put one array inside, I have to do this:
Array* array2d = array_create(sizeof(Array*), 0);
// Matrix 3x3
// first fill up
for(short row = 0; row<3; ++row) {
Array* tmp = array_create(sizeof(int), 3);
array_push(array2d, &tmp);
for(short col = 0; col<3; ++col) {
array_push(tmp, numbers+row*3+col);
}
}
// The double * here is just plain crazy...
printf("Final dimensions: %d rows, %d columns.\n", array2d->length, (*(Array**)array_get(array2d, 0))->length);
// Set some value at X Y
const size_t x = 1;
const size_t y = 1;
const int value = 666;
array_set(*(Array**)array_get(array2d, y), x, &value);
Array* row = NULL;
AR_FOREACH(row, array2d, Array*) {
AR_FOREACH(number, row, int) {
printf("%2d ", number);
}
printf("\n");
}
// Finally destroy all sub items and the array itself
// Note that the foreach loop here helps a lot by already changing Array** to Array*
AR_FOREACH(row, array2d, Array*) {
array_destroy(*row);
}
Note that I actually got several segfaults before I got this example to work. All of the errors came from me doing to many/not enough dereference operations. There were no errors from the library. The whole *(Array**)array_get(array2d, y)
is totally crazy.
I want to use this library for programming simple matrix operations, but can I first somehow make it less verbose? The only thing that comes to mind is manually writing all array2d_XXX
methods that work with two indexes.
Are there any C macros that could help me?
push
. Does that copyelm_size
bytes from the pointer? And does array get also copy said bytecount? The beauty of C is how the compiler blindly does what you say. Anyway, looks to me like it is still unfinished. Sadly, we neither write, debug, nor code review here, you might take it to code reviews SO.