I need to work upon a variable number of fixed-size arrays. More specifically, N points in a K-dimensional space, where I know K beforehand, but I don't know N at compile time. So I want to use a pointer to the fixed-size array, and allocate space for N K-dimensional points at runtime.
In C, I can allocate the said pointer with malloc. Example test.c
below, where dimension is 3 for simplicity:
#include <stdlib.h>
#include <stdio.h>
#define DIMENSIONS 3
typedef float PointKDimensions[DIMENSIONS];
void do_stuff( int num_points){
PointKDimensions *points;
points = malloc(num_points * sizeof(PointKDimensions));
points[5][0] = 0; // set value to 6th point, first dimension
points[5][1] = 1.0; // to second dimension
points[5][2] = 3.14; // to third dimension
return;
}
int main(){
do_stuff(10); // at run-time I find out I have 10 points to handle
return 0;
}
I can compile this with gcc test.c
without errors, and run without segmentation faults.
However, if I try to achieve the same behavior with C mv test.c test.cpp
, followed by g test.cpp
, I get:
test.cpp: In function ‘void do_stuff(int)’:
test.cpp:10:18: error: invalid conversion from ‘void*’ to ‘float (*)[3]’ [-fpermissive]
10 | points = malloc(num_points * sizeof(float) * DIMENSIONS);
| ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| void*
Searching up, I found that C does not do implicit conversions for malloc, so I changed the malloc to:
points = (float*) malloc(num_points * sizeof(float) * DIMENSIONS);
And then the error becomes:
test.cpp: In function ‘void do_stuff(int)’:
test.cpp:10:12: error: cannot convert ‘float*’ to ‘float (*)[3]’ in assignment
10 | points = (float*) malloc(num_points * sizeof(float) * DIMENSIONS);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| float*
But I could not find a way to do the appropriate cast/conversion to solve this error. E.g., (float**)
is also not the same as float(*)[3]
.
Any suggestions on how to allocate space for a pointer to fixed-sized arrays in C ?
CodePudding user response:
You could use std:array for that.
e.g.
#include <array>
inline constexpr const size_t DIMENSIONS = 3;
using PointKDimensions = std::array<float, DIMENSIONS>;
CodePudding user response:
You need to cast the result of malloc
as PointKDimensions*
not as a float*
:
typedef float PointKDimensions[DIMENSIONS];
void do_stuff( int num_points){
PointKDimensions *points;
points = (PointKDimensions*)malloc(num_points * sizeof(PointKDimensions));
points[5][0] = 0; // set value to 6th point, first dimension
points[5][1] = 1.0; // to second dimension
points[5][2] = 3.14; // to third dimension
return;
}
Or better, use C 's built-in container for dynamically sized arrays, std::vector
:
vector<vector<float>> points;
void do_stuff( int num_points){
points.resize(num_points, vector<float>(k)); // assuming k = number of dimensions.
points[5][0] = 0; // set value to 6th point, first dimension
points[5][1] = 1.0; // to second dimension
points[5][2] = 3.14; // to third dimension
return;
}