I am working with C to construct an array, which is then passed into Python (similar to: Embed python / numpy in C ). I am new to C and I am confused with some of the details of the code. I'm hoping I can get an understanding of how this code works, because I need to change it. So my question is: what is this method of initializing an array?
const int SIZE{ 10 };
double(*c_arr)[SIZE]{ new double[SIZE][SIZE] };
For the record, I've been able to make this a rectangular array by calling:
const int numberRows = 5000;
const int numberColumns = 500;
double(*c_arr)[numberColumns]{ new double[numberRows][numberColumns] };
I fill the array:
// fill the array from a file
std::string line;
int row = 0;
int column = 0;
while (std::getline(dataFile, line)) {
std::stringstream lineStream(line);
std::string cell;
while (std::getline(lineStream, cell, '\t')) {
c_arr[row][column] = std::stod(cell);
column ;
}
row ;
column = 0;
if (row == numberRows) {
break;
}
}
I still don't understand what is meant by double(*c_arr)
. Whenever I try to initialize this array differently, I get errors. For example: double *c_arr[numberRows][numberColumns];
raises errors when I try to fill the array c_arr[row][column] = std::stod(cell);
. If I change the initialization to be: double c_arr[numberRows][numberColumns];
, then I get a segmentation fault when run. What I'd like to eventually achieve is a function that returns a pointer to an array; something like:
double *load_data(int rows, int columns) {
double(*c_arr)[columns]{ new double[rows][columns] };
//fill array here
return (c_arr)
}
When I construct such a function, I get an error at the second occurrence of the columns
variable: expression must have a constant value -- the value of parameter "columns" cannot be used as a constant
. I don't really how to do this, but I'm hoping that if I can understand the array initialization, I'll be able to properly construct the load_data
function.
CodePudding user response:
double(*c_arr)[SIZE]{ new double[SIZE][SIZE] };
The above is/can be read as:
c_arr is a pointer to an array of size
SIZE
. Next,new double[SIZE][SIZE]
creates a 2D array and also returns a pointer to its first element(which is also an array of double). Next, the pointerc_arr
is initialized with the pointer returned in the last step fromnew double[SIZE][SIZE]
;
Now lets take a look at:
double *c_arr[numberRows][numberColumns];
In this case, c_arr
is a 2D array of pointers to double. And so you cannot initialize this 2D array of pointers with a single pointer like:
double d=15;
double *c_arr[5][6]=&d ;//incorrect
Now coming to your error:
When I construct such a function, I get an error at the second occurrence of the columns variable: expression must have a constant value -- the value of parameter "columns" cannot be used as a constant
This is because, in C the size of an array must be a compile time constant(constant expression
). So for example,
int n = 10;
double arr[n]; //incorrect
The correct way would be:
const int n = 10;
double arr[n];//correct
So in your code the variable named columns
is not a constant expression which is the reason you get the above mentioned error.
To correctly return a pointer to an array, you can modify your load_data
function to look like:
auto load_data(int rows, int columns) -> double (*)[5]{
double(*c_arr)[5]{ new double[4][5] };
//fill array here
return c_arr;
}
In the above modification of load_data
, instead of using the numbers 4 and 5 you can use other constant expressions.
CodePudding user response:
what is this method of initializing an array?
const int SIZE{ 10 }; double(*c_arr)[SIZE]{ new double[SIZE][SIZE] };
c_arr
is a pointer to double[SIZE]
i.e. pointer to array of doubles.
new double[SIZE][SIZE]
allocates a default initialised dynamic array of double[SIZE]
. The result is a pointer to the first element. That pointer is used to initialise c_arr
.