I am feeling a bit insecure about passing complicated, asymetrical data types & structure to functions, yet I would like to properly segment some of my source code for reusing. As tradeoff between human readability and performance I went for using a 'suboptimal' data format:
- one array consisting of
<number_of_curves>
non-identical curves, thei
-th curve being defined in<number_of_points>[i]
five-dimensionalpoints
.
In pseudo-code it looks so:
int number_of_curves;
int number_of_points[number_of_curves]; //aux. array storing number of points per curve
typedef struct point{
float x;
float y;
float z;
float v;
float w;
} point;
point array[number_of_curves][number_of_points[i]]; // 0 < i < number_of_curves
In practice, one cannot predict sizes and statically initialize any of the variables, so the code becomes:
int num_curves;
int *num_points;
point **array;
//read num_curves from file...
num_points = calloc(num_curves*sizeof(int));
//read the values for num_points[i] from file...
array = (point**)malloc(num_curves*sizeof(point*)); //few compilers doing strange things unless casted
for(int i = 0; i<num_curves; i++)
array[i] = (point*)malloc(num_points[i]*sizeof(point));
//read the values for array[i][j].x, array[i][j].y etc. from file...
Having not much experience in passing complicated data types to functions which should access and modify any member of any element in such arrays, change the order of elements, possibly resize the arrays, free and create new ones instead, I'm using the simplest function call:
int error = func1(&array, &num_points, &num_curves);
An apparently working example of a "dummy" func1()
, deleting odd members, passed basic functional tests.
I'm not sure about causing possible UB, memory leaks and fragmentation, which is difficult to debug.
This is what my question is about, I'm not asking for a code review.
Logical reasoning and understanding a bit of literature including:
Passing multidimensional arrays as function arguments in C
make me hope I'm on the right track in learning a safe way...
Here's the definition:
int func1 (point ***arrayPtr, int **num_pointsPtr, int *num_curvesPtr)
{
point **arr;
int i, j, k, *pts;
int crvs = *num_curvesPtr - (*num_curvesPtr)/2;
pts = malloc(crvs*sizeof(int));
if (pts == NULL) return 1;
for (i = 0; i < crvs; i++)
pts[i] = (*num_pointsPtr)[i+i];
arr = (point**)malloc(crvs*sizeof(point*));
if(arr == NULL){
free(pts);
return 2;
}
for (i = 0; i < crvs; i++){
arr[i] = (point*)malloc(pts[i]*sizeof(point));
if (arr[i] == NULL){
for(k = i-1; k >= 0; k --)
free(arr[k]);
free(arr);
free(pts);
return 3;
}
}
for (i = 0; i < crvs; i++)
for(j = 0; j < pts[i]; j++){
arr[i][j].x = (*arrayPtr)[i+i][j].x;
arr[i][j].y = (*arrayPtr)[i+i][j].y;
arr[i][j].z = (*arrayPtr)[i+i][j].z;
arr[i][j].v = (*arrayPtr)[i+i][j].v;
arr[i][j].w = (*arrayPtr)[i+i][j].w;
}
for(i = 0; i < *num_curvesPtr; i++)
free ((*arrayPtr)[i]);
free(*arrayPtr);
free(*num_pointsPtr);
*arrayPtr = arr;
*num_pointsPtr = pts;
*num_curvesPtr = crvs;
return 0;
}
Thanks for reading. Any hint if this is a valid direction would help me. Please let me know if something isn't clear.