0

I wrote a code and I don't know how it works. The scenario is the dynamic allocation of a 2D array in a function which reads an external file

void load_array(double **(&a), int *rows, int *random_val)
{
   //I know the number of columns e.g. 3
   int i,j;
   double temp;
   FILE *fp;


   //Assign a value to random variable
   *random_val=5;


   //Read file and determine number of lines(rows) block of code
   {
      //Code goes here
   }

    a=(double **)calloc((*rows),sizeof(double *);
    for(i=0;i<(*rows);i++)
    a[i]=(double **)calloc(2,sizeof(double *); //Only 2 collumns

    i=0;

    fp=fopen("input","r");
    fscanf(fp,"%lf\t%lf\n",&a[0][0],&a[0][1])
    while(!feof(fp))
    {
       i=i+1;
       fscanf(fp,"%lf\t%lf\n",&a[i][0],&a[i][1]);
    }
    *rows=i;
    fclose(fp);

}

int main(void)
{
    double **A;
    int row_count;
    double temp;
    load_array(A,&row_count, &temp);
    return 0;
}

I can't understand the following points:

  • Do I have to use the values in the function carrying the asterisk? For example for(i=0;i<rows;i++) instead of for(i=0;i<(*rows);i++) and random_val=5; instead of *random_val=5;?
  • Why I declare the function this way, using **(&a) for the array? Moreover I can't understand why to pass the array this way (without &).

My pointer knowledge is somewhat limited and I'm confused. Please do not propose std::vector. I would like to clarify first this point.

dimpep
  • 63
  • 1
  • 6
  • 3
    1) C and C++ are different languages, in C you use `malloc` to dynamically allocate memory, while in C++ it is preferred to use `new` or smart pointers 2) Please indent your code properly, this is undreadble. – user4520 Nov 15 '15 at 15:22
  • 2
    This is C++ code, as this `void load_array(double **(&a), int *rows, int *random_val)` won't get compiled by a C compiler. – alk Nov 15 '15 at 15:25
  • 2
    If this is C, you pass an uninitialized pointer to `load_array()` and `load_array()` has no way to modify the variable in `main()` — in no way does your code return an array to `main()`. Also in C, the parameter declaration `double **(&a)` won't compile; it is meaningless. The code must be C++; the mention of `std::vector` affirms that. Do not dual tag questions about C++ with the C tag too; it gets people cross. – Jonathan Leffler Nov 15 '15 at 15:26
  • 2
    Also, the `load_array()` function called in `main()` is not the one shown in the code; the function is called with two arguments but the function shown takes three. See also [`while (!feof(file))` is always wrong](http://stackoverflow.com/questions/5431941/while-feof-file-is-always-wrong). – Jonathan Leffler Nov 15 '15 at 15:32
  • 1
    And please indent your code properly, as it stands it is very difficult to read. – alk Nov 15 '15 at 15:34
  • Ok, thanks all for the remarks. But no one answered my questions. – dimpep Nov 15 '15 at 15:48
  • 1
    @szczurcio nope, in C++ you should almost never use `new`. For arrays, use `std::vector`. – n. m. could be an AI Nov 15 '15 at 16:28
  • @n.m. I agree, but OP is asking specifically about _dynamic 2D array allocation_, so maybe they have an assignment that requires them to do this stuff manually. – user4520 Nov 15 '15 at 16:30
  • 1
    Use `std::vector>& a`. "Please do not propose std::vector" The answers are for everyone's benefit, not just yours. Most people are better off with `std::vector`. – n. m. could be an AI Nov 15 '15 at 16:31
  • Usually (not always) if you know the number of columns beforehand and it is small, you want an array of struct/class types rather than a 2D array. – n. m. could be an AI Nov 15 '15 at 16:41

1 Answers1

2

You are mixing two languages because you pass a pointer-to-pointer argument by reference (double **(&a)) but you use C dynamic allocation through calloc, instead that new[] and delete[].

This just means you should read some documentation or guides before attempting to write random code.

If a variable is a pointer (eg int* rows) then you must dereference it (through * operator) to obtain its value or to assign a new value to it.

A variable declared with & (which is C++ only) is a reference to an existing variable (a sort of alias). Passing the array as in double **(&a) means that you are passing the reference to a double**, which under the hood is just a pointer to a pointer-to-pointer (a double***). In practice in your example this is used to pass an existing double** to the function to let the function initialize the array and store the resulting address directly in the passed argument. If you don't have any specific requirement to do so then you can just return a double** from the function instead that using references.

Jack
  • 131,802
  • 30
  • 241
  • 343
  • Thank you for the answer "In practice in your example this is used to pass an existing double** to the function to let the function initialize the array and store the resulting address directly in the passed argument." That's what I want to do. I could return a double** but in the more general case the function could be altered 2 or more arrays. Is there any other way to do this? Initialize the array in the function directly in the passed argument? – dimpep Nov 15 '15 at 15:53