Home > other >  Trying to understand initialization of array C
Trying to understand initialization of array C

Time:11-18

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 pointer c_arr is initialized with the pointer returned in the last step from new 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.

  • Related