Tell me how to correctly transfer a two-dimensional dynamic array to a function. The function does not return a value (void), the array in it should be changed. When passing to an argument just an int ** Arr, a copy is created and only a copy is changed, I need to change the array passed through the arguments.

void ArrayInput2(int **X, int n, int m, int **Y, int a, int b) { FILE *file; file = fopen("matrix.txt", "r"); int i, j; X = (int**)malloc(n * sizeof(int*)); for (i = 0; i<n; i++) { X[i] = (int*)malloc(m * sizeof(int)); for (j = 0; j<m; j++) { fscanf(file, "%d", &X[i][j]); } } Y = (int**)malloc(a * sizeof(int*)); for (i = 0; i<a; i++) { Y[i] = (int*)malloc(b * sizeof(int)); for (j = 0; j<b; j++) { fscanf(file, "%d", &Y[i][j]); } } fclose(file); } 
  • "When passing to an argument just an int ** Arr, a copy is created" - this is doubtful. - Igor
  • The function of filling the array from the file. The function itself works correctly, if you try to display the array read from the file immediately in the function, everything is output, but when you try to then output the same array from the main function, the program crashes ... - Uefa
  • Let your function return an int ** . - Igor
  • @Uefa Show the code. - HolyBlackCat
  • It does not work out, because From the file you need to read 2 arrays. The simplest way is to declare the function void and pass both functions through the arguments and, in 1 function call, write everything down. Otherwise, each time the function is called, the program writes the file data first to the array. - Uefa

2 answers 2

First of all, in such a situation you will have to pass the “return” parameters “according to a pointer”. Since the "returned" parameters themselves are of type int ** , then by passing "by pointer" they will turn into int ***

Secondly, in order not to be confused with asterisks, I would recommend making memory through the following idiom

 dst = malloc(N * sizeof *dst); 

(and at the same time get rid of the manners to explicitly give the result of malloc )

 void ArrayInput2(int ***pX, int n, int m, int ***pY, int a, int b) { ... *pX = malloc(n * sizeof **pX); for (int i = 0; i < n; ++i) { (*pX)[i] = malloc(m * sizeof *(*pX)[i]); for (int j = 0; j < m; ++j) fscanf(file, "%d", &(*pX)[i][j]); } ... 

Third, as an optional modification, you can offer to allocate second-level memory as a single unit, rather than with multiple calls to malloc

 void ArrayInput2(int ***pX, int n, int m, int ***pY, int a, int b) { ... *pX = malloc(n * sizeof **pX); **pX = malloc(n * m * sizeof ***pX); for (int i = 0; i < n; ++i) { (*pX)[i] = **pX + i * m; for (int j = 0; j < m; ++j) fscanf(file, "%d", &(*pX)[i][j]); } ... 

When calling such a function, of course, one must not forget to pass exactly pointers to pointers-receivers.

 int **X, **Y; ArrayInput2(&X, 10, 20, &Y, 30, 40); 

But, generally speaking, the code would have to be redone differently. A function that reads two matrices should not be. There must be a function that reads only one matrix from the given file and returns it via the return value.

 int **matrix_input(FILE *f, int n, int m) 

Then the "stars" of these high-rise would be less.

  • избавиться от манеры явно приводить результат malloc , if not a secret, why? What has not pleased such a caste? - NewView
  • @NewView: He didn’t please much. First, it is not needed. To do something unnecessary, and then asking "what did not please" is a strange occupation, especially if we are talking about something so ugly as a crutch, like caste. Castes in the code should not be at all, with rare exceptions when they are inevitable. - AnT
  • one
    Secondly, such a cast clogs the code by mentioning type names. Type names should be mentioned only in declarations. The code itself (statements) should be as type independent as possible. Mention of names of specific types should not be there (again: with rare exceptions when they are inevitable). This is the notorious DRY principle (don't repeat yourself): do not repeat what is already known. - AnT 7:49 pm
  • Two stars are enough in C, why three ?! - 0andriy
  • And multiplication to calculate the required memory size can theoretically cause an overflow of the whole. - 0andriy

But it is not easier to create a structure, and not to fence these three-story stars

 typedef struct matrix_s { int *data; size_t width; size_t height; } matrix_s; 

and function to create

 matrix_s *matrix_new(size_t w, size_t h); 

and pass it to your load function from a file, something like

 int load_matrix_fromfile(matrix_s *a, matrix_s *b, const char *filename) { FILE *fp = fopen(filename, "r"); if (!fp) return -1; for (size_t i = 0; i < a->width * a->height; i++) fscanf(fp, "%d", &a->data[i]); for (size_t i = 0; i < b->width * b->height; i++) fscanf(fp, "%d", &b->data[i]); fclose(fp); return 1; } 

and to read the matrix entries use

 int *matrix_setget(matrix_s *m, size_t x, size_t y) { return m->data + m->width * y + x; } matrix_s *m = matrix_new(3, 3); *matrix_setget(m, 0, 0) = 15; 

I think reading the code will be definitely nicer and clearer.

  • Maybe you should explain in the text of the answer that you are incl. suggest using a “real” matrix, rather than an array of pointers to rows (as in the question code) - avp
  • Well, I think this is understandable. - Anton
  • I understand that the vehicle and the newbies who came from Google are not sure - avp
  • @avp: And what is the "real" than the original version? First, both options are equivalent ways to implement a two-dimensional array (matrix). Each of them has its advantages and disadvantages and, accordingly, the scope. Secondly, the difference between these two options is not so great if you pay attention to the fact that the memory of the second level can easily be allocated as a single unit (as in my answer). - AnT
  • @AnT, in that memory is allocated the same way as for the matrix int a[N][M]; and there is no vector of pointers to lines (even if you allocate memory for all elements in one block (by the way, why do we need a vector of pointers in such a case? Will this not provoke errors?)). About the advantages of the method with a vector of pointers - imho only 1) natural for the programmer indexing of elements (without additional efforts) 2) theoretical possibility to work in extreme conditions of memory fragmentation - avp