I am writing a C program in which I have to carry out a search with an unknown number of results, place the results in some kind of structure, and then access that structure from various places in the program.
This looks to me like a place where the C handle object (a pointer to a pointer) is going to work nicely. I give the structure I want the program to access a handle, a pointer which does not change, so that any part of the program can get it. I have that stable handle point at some kind of array, which will be made during the program, and whose address will change as the data it holds grows or shrinks.
C has all you need to do this: pointers which can point at other pointers; dynamic allocation of memory for expanding objects. But: to do this in C you have to know how to use * ** & in combination with brackets ()[] and -> and period (.). You have to know, for example, that *(place+j) is the same as place[j], as is (*place)[j] and *(*place+j), and exactly how place->thing, place.thing, and (*place)->thing differ. And so on. So although I have been writing C programs for thirty years, it still took me hours to get this right.
Here is the code for a working solution. I have a structure process_book_inf containing two handles, pointing at the data I want to access. I want one of those handles to access an array of integers search_els_found, which might be any length. I want the other to access an array of pointers to bounds_obj structures, where again there might be any number of such structures. Two functions testInt and testPtr create two such arrays, creating new pointers to the arrays as they grow, and then putting the addresses of the new arrays into the master process_book structure.
Here is my question: my code works, but I'm not sure it is as elegant, simple, and transparent as it might be. There are many people more skilled in C than I am. Anyone have any ideas? (As a side note: this example demonstrates how powerful C can be).
#include <stdio.h>
#include <stdlib.h>
struct process_book_inf {
void *search_els_found;
void **search_texts_found;
};
typedef struct process_book_inf *process_book_ptr;
struct bounds_obj {
int start_el;
int start_off;
};
typedef struct bounds_obj *bounds_ptr;
void testInt(void **resultArray);
void testPtr(void **resultArray);
int main(int argc, const char * argv[]) {
process_book_ptr testMemory=malloc(sizeof(struct process_book_inf));
testInt((void **) &testMemory->search_els_found);
for (int c=0; c<5; c++) {
printf("retrieved %d\r", *((int *) (testMemory->search_els_found)+c));
}
testPtr((void **) &testMemory->search_texts_found);
for (int c=0; c<5; c++) {
bounds_ptr *dest= (bounds_ptr *) (testMemory->search_texts_found)+c;
printf("retrieved structure values %d %d\r", (*dest)->start_el, (*dest)->start_off);
}
return 0;
}
void testInt(void **testarray) {
int *place=(int *) malloc(sizeof(int));
int **already=(int **) testarray;
for (int c=0; c<5; c++) {
if (c>0) {
free(place);
place=(int *) malloc((c+1) *sizeof(int));
for (int j=0; j<c; j++){
place[j]=(*already)[j];
// *(place+j)=*(*already+j);
}
}
*(place+c)=c*100+c;
printf("set %d\r", *(place+c));
*already=place;
}
}
//in this version, simplify as far as I can
//replace *(place+j) by place[j]; remove all redundant casts
void testPtr(void **textarray) {
bounds_ptr *place= malloc(sizeof(bounds_ptr));
bounds_ptr **already=(bounds_ptr **) textarray;
for (int c=0; c<5; c++) {
if (c>0) {
free(place);
place= malloc(sizeof(bounds_ptr)*(c+1));
for (int j=0; j<c; j++){
place[j]= (*already)[j];
}
}
struct bounds_obj *dest= malloc(sizeof(struct bounds_obj));
dest->start_el=(c*100)+1;
dest->start_off=(c*100)+2;
place[c]=dest;
printf("set structure values %d %d\r", place[c]->start_el, place[c]->start_off);
*already= place;
}
}
The result of this is:
set 0
set 101
set 202
set 303
set 404
retrieved 0
retrieved 101
retrieved 202
retrieved 303
retrieved 404
set structure values 1 2
set structure values 101 102
set structure values 201 202
set structure values 301 302
set structure values 401 402
retrieved structure values 1 2
retrieved structure values 101 102
retrieved structure values 201 202
retrieved structure values 301 302
retrieved structure values 401 402
Program ended with exit code: 0