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?
 
    