I'm building a program in C to run some simulations for my PhD research. Basically the program uses a function to read an input file with some important values, and then assign these values to variables in the main
function. Some of these values need to be assigned to arrays, x
and par
, with size also declared in the input file. For that, I need to use some dynamically allocated memory inside the function, that points to the address of the pointers *x
and *par
.
I manage to assign the values for these pointers using 2D array notation, but I don't fully understand why it needs to be this way, as the pointers that the function are pointing to are initialized as NULL
pointers.
Here is the minimum functional code as an example:
#include <stdio.h>
#include <stdlib.h>
void read_input(char *name, int *dim, int *npar, int *np, int *ndiv, double *t, double **par, double **x);
int main(void) {
int DIM;
int nP;
int nDiv;
int nPar;
// Assign values for program parameters, system parameters and initial conditions
char *input_filename = "input.txt";
double t;
double *par = NULL;
double *x = NULL;
read_input(input_filename, &DIM, &nPar, &nP, &nDiv, &t, &par, &x);
for (int i = 0; i < DIM; i++) {
printf("x[%i] = %.15lf\n", i, x[i]);
}
for (int i = 0; i < nPar; i++) {
printf("par[%i] = %lf\n", i, par[i]);
}
free(x);
free(par);
}
void read_input(char *name, int *dim, int *npar, int *np, int *ndiv, double *t, double **par, double **x) {
// Open input file
FILE *input = fopen(name, "r");
if (input == NULL) {
printf("Input File Not Found...\n");
return;
}
// Read and assign system constants
fscanf(input, "%i", dim);
fscanf(input, "%i", npar);
// Read and assign program parameters
fscanf(input, "%i %i", np, ndiv);
// Read and assign initial time
fscanf(input, "%lf", t);
// Allocate memory for x[dim] and par[npar] vectors
*x = malloc((*dim) * sizeof(double));
*par = malloc((*npar) * sizeof(double));
// Security check for pointers
if (*x == NULL || *par == NULL) {
free(*x);
free(*par);
printf("Memory allocation for *x or *par did not complete successfully");
return;
}
// assign IC to x[dim] vector
for (int i = 0; i < *dim; i++) {
fscanf(input, "%lf ", &x[i][i]);
}
for (int i = 0; i < *dim; i++) {
for (int j = 0; j < *dim; j++) {
printf("x[%i][%i] = %lf (address: %p)\n", i, j, x[i][j], &x[i][j]);
}
}
printf("==============================\n");
// Assign values to par[npar] vector
for (int i = 0; i < *npar; i++) {
fscanf(input, "%lf\n", &par[i][i]);
}
for (int i = 0; i < *npar; i++) {
for (int j = 0; j < *npar; j++) {
printf("par[%i][%i] = %lf (address: %p)\n", i, j, par[i][j], &par[i][j]);
}
}
printf("==============================\n");
// Close input file
fclose(input);
}
Also, I checked the addresses that the double pointers x[i][j]
and par[i][j]
are pointing to, and they are the same for each combination of [i][0], ..., [i][4]
, with i = 0 to 4
:
x[0][0] = 0.707107 (address: 0000020B01C33FC0)
x[0][1] = 0.000000 (address: 0000020B01C33FC8)
x[1][0] = 0.707107 (address: 0000020B01C33FC0)
x[1][1] = 0.000000 (address: 0000020B01C33FC8)
==============================
par[0][0] = 1.000000 (address: 0000020B01C34580)
par[0][1] = 0.150000 (address: 0000020B01C34588)
par[0][2] = 0.025000 (address: 0000020B01C34590)
par[0][3] = -0.500000 (address: 0000020B01C34598)
par[0][4] = 1.000000 (address: 0000020B01C345A0)
par[1][0] = 1.000000 (address: 0000020B01C34580)
par[1][1] = 0.150000 (address: 0000020B01C34588)
par[1][2] = 0.025000 (address: 0000020B01C34590)
par[1][3] = -0.500000 (address: 0000020B01C34598)
par[1][4] = 1.000000 (address: 0000020B01C345A0)
par[2][0] = 1.000000 (address: 0000020B01C34580)
par[2][1] = 0.150000 (address: 0000020B01C34588)
par[2][2] = 0.025000 (address: 0000020B01C34590)
par[2][3] = -0.500000 (address: 0000020B01C34598)
par[2][4] = 1.000000 (address: 0000020B01C345A0)
par[3][0] = 1.000000 (address: 0000020B01C34580)
par[3][1] = 0.150000 (address: 0000020B01C34588)
par[3][2] = 0.025000 (address: 0000020B01C34590)
par[3][3] = -0.500000 (address: 0000020B01C34598)
par[3][4] = 1.000000 (address: 0000020B01C345A0)
par[4][0] = 1.000000 (address: 0000020B01C34580)
par[4][1] = 0.150000 (address: 0000020B01C34588)
par[4][2] = 0.025000 (address: 0000020B01C34590)
par[4][3] = -0.500000 (address: 0000020B01C34598)
par[4][4] = 1.000000 (address: 0000020B01C345A0)
==============================
x[0] = 0.707106781186547
x[1] = 0.000000000000000
par[0] = 1.000000
par[1] = 0.150000
par[2] = 0.025000
par[3] = -0.500000
par[4] = 1.000000
Here is the format of the input.txt file:
2
5
1000 1000
0.0
0.707106781186547 0.0
1.0
0.15
0.025
-0.5
1.0
What am I missing here?