S
A little theory.The C does not have dynamic arrays (whose size is chosen in execution time) properly said, but can build them by pointers.One-dimensional ArraysFor a unidimemsional array (also called a vector), it is used malloc() to reserve as much memory as necessary for its elements. Malloc must pass the size on bytes, so if each element is, for example, of an entire type and we need N elements, the initialization would be:int *vector_dinamico;
int N = 50;
vector_dinamico = malloc(N*sizeof(int));
Once the pointer is initialized, we can disrefer it (put a * to access the first element of the array, for example, to assign a zero to that element: *vector_dinamico=0;But what about the following elements?Because C has what is called arithmetic pointers You can add an index. i to the pointer to get the memory address in which the element would be i- That's good. I mean (vector_dinamico+i) will give you the direction of the element i- That's great. To assign a value you can unrefer that direction and put for example: *(vector_dinamico+i)=0;A loop that starts with zeros all the elements of this vector would therefore be:for (int i=0; i<N, i++)
*(vector_dinamico+i) = 0;
You probably haven't seen this syntax many times, because it's a bit uncomfortable and the C allows another alternative syntax that is the following:for (int i=0; i<N, i++)
vector_dinamico[i] = 0;
This syntax has as an advantage that is identical to that of the arrays. But it is inconvenient that it is identical to that of the arrays so many novel programmers mistake both. Actually vector_dinamico is not an array, but a pointer to a memory area where there is an array. The fact that we can use the syntax a[i] is because the compiler automatically translates it to *(a+i).Also, to stop messing with the rookie programmer, the compiler supports the following two syntaxes as equivalent to defining a function that receives as a parameter a dynamic vector:int sumar_elementos(int *vector, int n_elem);
// Es equivalente a
int sumar_elementos(int vector[], int n_elem);
Again the existence of these two equivalent syntaxes helps to reinforce the wrong idea that arrays and pointers come to be the same.Two-dimensional ArraysA two-dimensional array (matriz) can be understood as a vector in which each of its elements is a row of the matrix, that is, another vector.With this idea in the head, since each row of the matrix is a one-dimensional vector, each row will be managed by a pointer that will target the data in that row. On the other hand, the "bidimensional aray" will only be an array whose elements are those pointers.If we knew in advance how many rows our matrix has, we could create a fixed-size array with that number of elements, each being a pointer. For example, assuming there are 10 rows:int *array_dinamico[10];
This is declaring a vector of 10 elements, each of them being int *, that is, a pointer (we will point to each row of the matrix).Since array_dinamico is an array, could use the "normal" syntax to access its elements, and so array_dinamico[0] I would get the first element of that vector, which is a vector pointer that contains the integers of the first row of the matrix. Since array_dinamico[0] It's a whole pointer, I can use the syntax. *(array_dinamico[0]+i) to access the element i- That's a line. Therefore, I can generally use *(array_dinamico[j]+i) to access the element i-thousand of the row j- Sixty.Again that syntax is not usually seen much, because instead it is used this other, much more pleasant: array_dinamico[j][i]. The one that this syntax is valid is deducted from what has already been said about one-dimensional arrays.But what if the number of rows of the array is not known in advance, but we want to choose it in execution time? In that case we can no longer declare it by putting a [10].We will use the same viewing technique for single-dimensional arrays. There, when we wanted to book dynamically N elements, we use a malloc() to create memory for them. We can do the same here, but bearing in mind that now every element is of the type int* (the pointer to the row). Therefore the pointer to my array will be of type int** (point to pointer).For example, if M is the number of rows of the matrix:int **array_dinamico;
int M = 8;
array_dinamico = malloc(M*sizeof(int *));
This reserves space for the 8 pointers corresponding to the 8 rows of the matrix we are creating. But those 8 pointers still have no value because we haven't created any of the 8 rows. To do this we should call another 8 times malloc(), to create each row, and save the returned value in each element of the array. For example:for (int i = 0; i<M, i++)
array_dinamico[i] = malloc(N*sizeof(int));
With all this we would have the M row array and N columns already dynamically reserved, although we have not yet initialized their values.Step of these arrays as parameterWe already saw that in the case of one-dimensional arrays the C allows to declare the parameters with two equivalent syntaxes: int *paramor int param[]. Both are the same because the compiler knows what he needs to know to compile an expression as param[5]. You know that param points to the beginning of the array and that each element is of type int, so you can calculate how many bytes you must advance within the array to reach element 5.Instead if the array is two-dimensional, something like int param[][] does not serve the compiler, so how many bytes should be moved to get to param[5] In this case? In order to calculate it you would need to know the size of each row, and that does not appear in the statement.We can fix that statement if we change it for this other: int *param[]. Here we tell you that the parameter is a vector in which each element is of type int*. Now you can know that to get to param[5] you must add to the beginning address (param) the size of a pointer multiplied by 5. Once you reach that element, we will have a pointer to the corresponding row, so the expression param[5][3] I could also compile it correctly (I would go to the address indicated by param more than five times the size of a pointer, and from there would be another pointer, which would add 3 times the size of an integer to finally reach the desired value.Answering your question alreadyI'm sorry for the long tour before you get to what you're interested in, but in this way it is already written and explained the subject of pointers and arrays, in case in the future I have to redirect someone else to this question The above has been explained why void imprimirMatriz(int matriz[][], int n) It didn't work.Based on the above, it follows that you have two possible solutions, both equivalents (it is mere a matter of taste to choose one or another):void imprimiMatriz(int *matriz[], int n)
// O, equivalentemente
void imprimirMatriz(int **matriz, int n)
Postdata. Your program has other mistakes. When you call imprimirMatriz You have to pass the address that the pointer points mat1That's where the pointer vector is (every one to a row).
Instead you pass him &mat1which is not the direction to which the pointer points, but the direction where the pointer is stored. That's wrong, but the error is understandable because of the easy confusion between pointers and arrays, due to the syntactic sugar C.Another mistake you have is that you do not release memory properly. Even though you do free(mat1), this only releases the memory you created for the "door-on- row reader", but you need to call others N Sometimes free() to release each of those pointers. In fact, you have to free first each of the rows and then the "principal" pointer (since you do it in reverse order, once the general pointer has been released you can no longer access the pointers of each row).