I am trying to allocate a matrix using a function that takes its dimensions and a triple pointer. I have allocated an int** (set to NULL) and I am passing its address as the function's argument. That gives me a mem access violation for some reason.
void allocateMatrix(int ***matrix, int row, int col)
{
int i;
if((*matrix = (int**)malloc(row * sizeof(int*))) == NULL)
{
perror("There has been an error");
exit(EXIT_FAILURE);
}
for(i = 0; i < row; ++i)
{
if((*matrix[i] = (int*)malloc(col * sizeof(int))) == NULL)
{
perror("There has been an error");
exit(EXIT_FAILURE);
}
}
}
/* main.c */
int** matrix = NULL;
allocateMatrix(&matrix, MATRIX_ROW, MATRIX_COL); //error
You need to change
if((*matrix[i] = (int*)malloc(col * sizeof(int))) == NULL)
to
if(((*matrix)[i] = (int*)malloc(col * sizeof(int))) == NULL)
// ^ ^
You need to dereference matrix before using the array subscript.
*matrix[i] is equivalent to *(matrix[i])
It's a problem of operator precedence. In
if ((*matrix[i] = (int*)malloc( ... ))
the default precedence is *(matrix[i]), while you should use (*matrix)[i].
I would still recommend to allocate the matrix as a contiguous array instead as a array of pointers to arrays.
I have made a solution program for gcc C11/C99 with apropriate allocation funtions based on links:
http://c-faq.com/aryptr/dynmuldimary.html
http://c-faq.com/aryptr/ary2dfunc3.html
After some discussion in comments, it is clear that matrix2 is correctly allocated, it can be passed to this function fn(int row, int col, int array[col][row]) as matrix2[0] (data in one dimensional array) with a cast to (double (*)[])
//compile with gcc --std=c11 program.c
#include <stdio.h>
#include <stdlib.h>
#define MX 9
#define MY 14
void input_matrix(int row, int column, double matrix[row][column]);
void print_matrix(int row, int column, double matrix[row][column]);
double **alloc_matrix2(int row, int column);
double *alloc_matrix3(int row, int column);
void *alloc_matrix4(int row, int column);
int main()
{
int i=MX, j=MY;
printf("Generate input values and print matrices with functions fn(int w, int k, double matrix[w][k]) (in C99 and C11)\n");
double matrix1[i][j];
input_matrix(MX,MY,matrix1);
printf("matrix static\n");
print_matrix(MX,MY,matrix1);
double **matrix2; //data of matrix2 is just matrix3
matrix2=alloc_matrix2(MX,MY);
input_matrix(MX,MY,(double (*)[])(*matrix2));
printf("matrix two times allocated one for pointers, the second for data (double (*)[])(m[0])\n");
print_matrix(MX,MY,(double (*)[])(matrix2[0]));
free(*matrix2);
free(matrix2);
double *matrix3=alloc_matrix3(MX,MY);
input_matrix(MX,MY,(double (*)[])matrix3);
printf("matrix allocated as two-dimensional array\n");
print_matrix(MX,MY,(double (*)[])matrix3);
free(matrix3);
j=MY;
double (*matrix4)[j];
matrix4 = (double (*)[])alloc_matrix4(MX,MY);
input_matrix(MX,MY,matrix4);
printf("matrix allocated via pointer to array m = (double (*)[])malloc(MX * sizeof(*m))\n");
print_matrix(MX,MY,matrix4);
free(matrix4);
printf("\nThe End!\n");
return 0;
}
void input_matrix(int row, int column, double matrix[row][column]){
for(int i=0; i<row; i++){
for(int j=0; j<column; j++)
matrix[i][j]=i+1;
}
}
void print_matrix(int row, int column, double matrix[row][column]){
for(int i=0; i<row; i++){
for(int j=0; j<column; j++)
printf("%.2lf ", matrix[i][j]);
printf("\n");
}
}
double **alloc_matrix2(int row, int column){
double **matrix;
matrix=malloc(row*sizeof(double*));
matrix[0] = (double *)malloc(row*column*sizeof(double));
for(int i = 1; i < row; i++)
matrix[i] = matrix[0]+i*column;
return matrix;
}
double *alloc_matrix3(int row, int column){
double *matrix;
matrix=malloc(row*column*sizeof(double));
return matrix;
}
void *alloc_matrix4(int row, int column){
double (*matrix)[column];
matrix = (double (*)[])malloc(row*sizeof(*matrix));
return matrix;
}
Related
I need to do this to persist operations on the matrix as well. Does that mean that it needs to be passed by reference?
Will this suffice?
void operate_on_matrix(char matrix[][20]);
C does not really have multi-dimensional arrays, but there are several ways to simulate them. The way to pass such arrays to a function depends on the way used to simulate the multiple dimensions:
1) Use an array of arrays. This can only be used if your array bounds are fully determined at compile time, or if your compiler supports VLA's:
#define ROWS 4
#define COLS 5
void func(int array[ROWS][COLS])
{
int i, j;
for (i=0; i<ROWS; i++)
{
for (j=0; j<COLS; j++)
{
array[i][j] = i*j;
}
}
}
void func_vla(int rows, int cols, int array[rows][cols])
{
int i, j;
for (i=0; i<rows; i++)
{
for (j=0; j<cols; j++)
{
array[i][j] = i*j;
}
}
}
int main()
{
int x[ROWS][COLS];
func(x);
func_vla(ROWS, COLS, x);
}
2) Use a (dynamically allocated) array of pointers to (dynamically allocated) arrays. This is used mostly when the array bounds are not known until runtime.
void func(int** array, int rows, int cols)
{
int i, j;
for (i=0; i<rows; i++)
{
for (j=0; j<cols; j++)
{
array[i][j] = i*j;
}
}
}
int main()
{
int rows, cols, i;
int **x;
/* obtain values for rows & cols */
/* allocate the array */
x = malloc(rows * sizeof *x);
for (i=0; i<rows; i++)
{
x[i] = malloc(cols * sizeof *x[i]);
}
/* use the array */
func(x, rows, cols);
/* deallocate the array */
for (i=0; i<rows; i++)
{
free(x[i]);
}
free(x);
}
3) Use a 1-dimensional array and fixup the indices. This can be used with both statically allocated (fixed-size) and dynamically allocated arrays:
void func(int* array, int rows, int cols)
{
int i, j;
for (i=0; i<rows; i++)
{
for (j=0; j<cols; j++)
{
array[i*cols+j]=i*j;
}
}
}
int main()
{
int rows, cols;
int *x;
/* obtain values for rows & cols */
/* allocate the array */
x = malloc(rows * cols * sizeof *x);
/* use the array */
func(x, rows, cols);
/* deallocate the array */
free(x);
}
4) Use a dynamically allocated VLA. One advantage of this over option 2 is that there is a single memory allocation; another is that less memory is needed because the array of pointers is not required.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
extern void func_vla(int rows, int cols, int array[rows][cols]);
extern void get_rows_cols(int *rows, int *cols);
extern void dump_array(const char *tag, int rows, int cols, int array[rows][cols]);
void func_vla(int rows, int cols, int array[rows][cols])
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
array[i][j] = (i + 1) * (j + 1);
}
}
}
int main(void)
{
int rows, cols;
get_rows_cols(&rows, &cols);
int (*array)[cols] = malloc(rows * cols * sizeof(array[0][0]));
/* error check omitted */
func_vla(rows, cols, array);
dump_array("After initialization", rows, cols, array);
free(array);
return 0;
}
void dump_array(const char *tag, int rows, int cols, int array[rows][cols])
{
printf("%s (%dx%d):\n", tag, rows, cols);
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
printf("%4d", array[i][j]);
putchar('\n');
}
}
void get_rows_cols(int *rows, int *cols)
{
srand(time(0)); // Only acceptable because it is called once
*rows = 5 + rand() % 10;
*cols = 3 + rand() % 12;
}
(See srand() — why call it only once?.)
Easiest Way in Passing A Variable-Length 2D Array
Most clean technique for both C & C++ is: pass 2D array like a 1D array, then use as 2D inside the function.
#include <stdio.h>
void func(int row, int col, int* matrix){
int i, j;
for(i=0; i<row; i++){
for(j=0; j<col; j++){
printf("%d ", *(matrix + i*col + j)); // or better: printf("%d ", *matrix++);
}
printf("\n");
}
}
int main(){
int matrix[2][3] = { {0, 1, 2}, {3, 4, 5} };
func(2, 3, matrix[0]);
return 0;
}
Internally, no matter how many dimensions an array has, C/C++ always maintains a 1D array. And so, we can pass any multi-dimensional array like this.
I don't know what you mean by "data dont get lost". Here's how you pass a normal 2D array to a function:
void myfunc(int arr[M][N]) { // M is optional, but N is required
..
}
int main() {
int somearr[M][N];
...
myfunc(somearr);
...
}
2D array:
int sum(int array[][COLS], int rows)
{
}
3D array:
int sum(int array[][B][C], int A)
{
}
4D array:
int sum(int array[][B][C][D], int A)
{
}
and nD array:
int sum(int ar[][B][C][D][E][F].....[N], int A)
{
}
I need to do this to persist operations on the matrix as well. Does that mean that it needs to be passed by reference?
Will this suffice?
void operate_on_matrix(char matrix[][20]);
C does not really have multi-dimensional arrays, but there are several ways to simulate them. The way to pass such arrays to a function depends on the way used to simulate the multiple dimensions:
1) Use an array of arrays. This can only be used if your array bounds are fully determined at compile time, or if your compiler supports VLA's:
#define ROWS 4
#define COLS 5
void func(int array[ROWS][COLS])
{
int i, j;
for (i=0; i<ROWS; i++)
{
for (j=0; j<COLS; j++)
{
array[i][j] = i*j;
}
}
}
void func_vla(int rows, int cols, int array[rows][cols])
{
int i, j;
for (i=0; i<rows; i++)
{
for (j=0; j<cols; j++)
{
array[i][j] = i*j;
}
}
}
int main()
{
int x[ROWS][COLS];
func(x);
func_vla(ROWS, COLS, x);
}
2) Use a (dynamically allocated) array of pointers to (dynamically allocated) arrays. This is used mostly when the array bounds are not known until runtime.
void func(int** array, int rows, int cols)
{
int i, j;
for (i=0; i<rows; i++)
{
for (j=0; j<cols; j++)
{
array[i][j] = i*j;
}
}
}
int main()
{
int rows, cols, i;
int **x;
/* obtain values for rows & cols */
/* allocate the array */
x = malloc(rows * sizeof *x);
for (i=0; i<rows; i++)
{
x[i] = malloc(cols * sizeof *x[i]);
}
/* use the array */
func(x, rows, cols);
/* deallocate the array */
for (i=0; i<rows; i++)
{
free(x[i]);
}
free(x);
}
3) Use a 1-dimensional array and fixup the indices. This can be used with both statically allocated (fixed-size) and dynamically allocated arrays:
void func(int* array, int rows, int cols)
{
int i, j;
for (i=0; i<rows; i++)
{
for (j=0; j<cols; j++)
{
array[i*cols+j]=i*j;
}
}
}
int main()
{
int rows, cols;
int *x;
/* obtain values for rows & cols */
/* allocate the array */
x = malloc(rows * cols * sizeof *x);
/* use the array */
func(x, rows, cols);
/* deallocate the array */
free(x);
}
4) Use a dynamically allocated VLA. One advantage of this over option 2 is that there is a single memory allocation; another is that less memory is needed because the array of pointers is not required.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
extern void func_vla(int rows, int cols, int array[rows][cols]);
extern void get_rows_cols(int *rows, int *cols);
extern void dump_array(const char *tag, int rows, int cols, int array[rows][cols]);
void func_vla(int rows, int cols, int array[rows][cols])
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
array[i][j] = (i + 1) * (j + 1);
}
}
}
int main(void)
{
int rows, cols;
get_rows_cols(&rows, &cols);
int (*array)[cols] = malloc(rows * cols * sizeof(array[0][0]));
/* error check omitted */
func_vla(rows, cols, array);
dump_array("After initialization", rows, cols, array);
free(array);
return 0;
}
void dump_array(const char *tag, int rows, int cols, int array[rows][cols])
{
printf("%s (%dx%d):\n", tag, rows, cols);
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
printf("%4d", array[i][j]);
putchar('\n');
}
}
void get_rows_cols(int *rows, int *cols)
{
srand(time(0)); // Only acceptable because it is called once
*rows = 5 + rand() % 10;
*cols = 3 + rand() % 12;
}
(See srand() — why call it only once?.)
Easiest Way in Passing A Variable-Length 2D Array
Most clean technique for both C & C++ is: pass 2D array like a 1D array, then use as 2D inside the function.
#include <stdio.h>
void func(int row, int col, int* matrix){
int i, j;
for(i=0; i<row; i++){
for(j=0; j<col; j++){
printf("%d ", *(matrix + i*col + j)); // or better: printf("%d ", *matrix++);
}
printf("\n");
}
}
int main(){
int matrix[2][3] = { {0, 1, 2}, {3, 4, 5} };
func(2, 3, matrix[0]);
return 0;
}
Internally, no matter how many dimensions an array has, C/C++ always maintains a 1D array. And so, we can pass any multi-dimensional array like this.
I don't know what you mean by "data dont get lost". Here's how you pass a normal 2D array to a function:
void myfunc(int arr[M][N]) { // M is optional, but N is required
..
}
int main() {
int somearr[M][N];
...
myfunc(somearr);
...
}
2D array:
int sum(int array[][COLS], int rows)
{
}
3D array:
int sum(int array[][B][C], int A)
{
}
4D array:
int sum(int array[][B][C][D], int A)
{
}
and nD array:
int sum(int ar[][B][C][D][E][F].....[N], int A)
{
}
I need to do this to persist operations on the matrix as well. Does that mean that it needs to be passed by reference?
Will this suffice?
void operate_on_matrix(char matrix[][20]);
C does not really have multi-dimensional arrays, but there are several ways to simulate them. The way to pass such arrays to a function depends on the way used to simulate the multiple dimensions:
1) Use an array of arrays. This can only be used if your array bounds are fully determined at compile time, or if your compiler supports VLA's:
#define ROWS 4
#define COLS 5
void func(int array[ROWS][COLS])
{
int i, j;
for (i=0; i<ROWS; i++)
{
for (j=0; j<COLS; j++)
{
array[i][j] = i*j;
}
}
}
void func_vla(int rows, int cols, int array[rows][cols])
{
int i, j;
for (i=0; i<rows; i++)
{
for (j=0; j<cols; j++)
{
array[i][j] = i*j;
}
}
}
int main()
{
int x[ROWS][COLS];
func(x);
func_vla(ROWS, COLS, x);
}
2) Use a (dynamically allocated) array of pointers to (dynamically allocated) arrays. This is used mostly when the array bounds are not known until runtime.
void func(int** array, int rows, int cols)
{
int i, j;
for (i=0; i<rows; i++)
{
for (j=0; j<cols; j++)
{
array[i][j] = i*j;
}
}
}
int main()
{
int rows, cols, i;
int **x;
/* obtain values for rows & cols */
/* allocate the array */
x = malloc(rows * sizeof *x);
for (i=0; i<rows; i++)
{
x[i] = malloc(cols * sizeof *x[i]);
}
/* use the array */
func(x, rows, cols);
/* deallocate the array */
for (i=0; i<rows; i++)
{
free(x[i]);
}
free(x);
}
3) Use a 1-dimensional array and fixup the indices. This can be used with both statically allocated (fixed-size) and dynamically allocated arrays:
void func(int* array, int rows, int cols)
{
int i, j;
for (i=0; i<rows; i++)
{
for (j=0; j<cols; j++)
{
array[i*cols+j]=i*j;
}
}
}
int main()
{
int rows, cols;
int *x;
/* obtain values for rows & cols */
/* allocate the array */
x = malloc(rows * cols * sizeof *x);
/* use the array */
func(x, rows, cols);
/* deallocate the array */
free(x);
}
4) Use a dynamically allocated VLA. One advantage of this over option 2 is that there is a single memory allocation; another is that less memory is needed because the array of pointers is not required.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
extern void func_vla(int rows, int cols, int array[rows][cols]);
extern void get_rows_cols(int *rows, int *cols);
extern void dump_array(const char *tag, int rows, int cols, int array[rows][cols]);
void func_vla(int rows, int cols, int array[rows][cols])
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
array[i][j] = (i + 1) * (j + 1);
}
}
}
int main(void)
{
int rows, cols;
get_rows_cols(&rows, &cols);
int (*array)[cols] = malloc(rows * cols * sizeof(array[0][0]));
/* error check omitted */
func_vla(rows, cols, array);
dump_array("After initialization", rows, cols, array);
free(array);
return 0;
}
void dump_array(const char *tag, int rows, int cols, int array[rows][cols])
{
printf("%s (%dx%d):\n", tag, rows, cols);
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
printf("%4d", array[i][j]);
putchar('\n');
}
}
void get_rows_cols(int *rows, int *cols)
{
srand(time(0)); // Only acceptable because it is called once
*rows = 5 + rand() % 10;
*cols = 3 + rand() % 12;
}
(See srand() — why call it only once?.)
Easiest Way in Passing A Variable-Length 2D Array
Most clean technique for both C & C++ is: pass 2D array like a 1D array, then use as 2D inside the function.
#include <stdio.h>
void func(int row, int col, int* matrix){
int i, j;
for(i=0; i<row; i++){
for(j=0; j<col; j++){
printf("%d ", *(matrix + i*col + j)); // or better: printf("%d ", *matrix++);
}
printf("\n");
}
}
int main(){
int matrix[2][3] = { {0, 1, 2}, {3, 4, 5} };
func(2, 3, matrix[0]);
return 0;
}
Internally, no matter how many dimensions an array has, C/C++ always maintains a 1D array. And so, we can pass any multi-dimensional array like this.
I don't know what you mean by "data dont get lost". Here's how you pass a normal 2D array to a function:
void myfunc(int arr[M][N]) { // M is optional, but N is required
..
}
int main() {
int somearr[M][N];
...
myfunc(somearr);
...
}
2D array:
int sum(int array[][COLS], int rows)
{
}
3D array:
int sum(int array[][B][C], int A)
{
}
4D array:
int sum(int array[][B][C][D], int A)
{
}
and nD array:
int sum(int ar[][B][C][D][E][F].....[N], int A)
{
}
I need to do this to persist operations on the matrix as well. Does that mean that it needs to be passed by reference?
Will this suffice?
void operate_on_matrix(char matrix[][20]);
C does not really have multi-dimensional arrays, but there are several ways to simulate them. The way to pass such arrays to a function depends on the way used to simulate the multiple dimensions:
1) Use an array of arrays. This can only be used if your array bounds are fully determined at compile time, or if your compiler supports VLA's:
#define ROWS 4
#define COLS 5
void func(int array[ROWS][COLS])
{
int i, j;
for (i=0; i<ROWS; i++)
{
for (j=0; j<COLS; j++)
{
array[i][j] = i*j;
}
}
}
void func_vla(int rows, int cols, int array[rows][cols])
{
int i, j;
for (i=0; i<rows; i++)
{
for (j=0; j<cols; j++)
{
array[i][j] = i*j;
}
}
}
int main()
{
int x[ROWS][COLS];
func(x);
func_vla(ROWS, COLS, x);
}
2) Use a (dynamically allocated) array of pointers to (dynamically allocated) arrays. This is used mostly when the array bounds are not known until runtime.
void func(int** array, int rows, int cols)
{
int i, j;
for (i=0; i<rows; i++)
{
for (j=0; j<cols; j++)
{
array[i][j] = i*j;
}
}
}
int main()
{
int rows, cols, i;
int **x;
/* obtain values for rows & cols */
/* allocate the array */
x = malloc(rows * sizeof *x);
for (i=0; i<rows; i++)
{
x[i] = malloc(cols * sizeof *x[i]);
}
/* use the array */
func(x, rows, cols);
/* deallocate the array */
for (i=0; i<rows; i++)
{
free(x[i]);
}
free(x);
}
3) Use a 1-dimensional array and fixup the indices. This can be used with both statically allocated (fixed-size) and dynamically allocated arrays:
void func(int* array, int rows, int cols)
{
int i, j;
for (i=0; i<rows; i++)
{
for (j=0; j<cols; j++)
{
array[i*cols+j]=i*j;
}
}
}
int main()
{
int rows, cols;
int *x;
/* obtain values for rows & cols */
/* allocate the array */
x = malloc(rows * cols * sizeof *x);
/* use the array */
func(x, rows, cols);
/* deallocate the array */
free(x);
}
4) Use a dynamically allocated VLA. One advantage of this over option 2 is that there is a single memory allocation; another is that less memory is needed because the array of pointers is not required.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
extern void func_vla(int rows, int cols, int array[rows][cols]);
extern void get_rows_cols(int *rows, int *cols);
extern void dump_array(const char *tag, int rows, int cols, int array[rows][cols]);
void func_vla(int rows, int cols, int array[rows][cols])
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
array[i][j] = (i + 1) * (j + 1);
}
}
}
int main(void)
{
int rows, cols;
get_rows_cols(&rows, &cols);
int (*array)[cols] = malloc(rows * cols * sizeof(array[0][0]));
/* error check omitted */
func_vla(rows, cols, array);
dump_array("After initialization", rows, cols, array);
free(array);
return 0;
}
void dump_array(const char *tag, int rows, int cols, int array[rows][cols])
{
printf("%s (%dx%d):\n", tag, rows, cols);
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
printf("%4d", array[i][j]);
putchar('\n');
}
}
void get_rows_cols(int *rows, int *cols)
{
srand(time(0)); // Only acceptable because it is called once
*rows = 5 + rand() % 10;
*cols = 3 + rand() % 12;
}
(See srand() — why call it only once?.)
Easiest Way in Passing A Variable-Length 2D Array
Most clean technique for both C & C++ is: pass 2D array like a 1D array, then use as 2D inside the function.
#include <stdio.h>
void func(int row, int col, int* matrix){
int i, j;
for(i=0; i<row; i++){
for(j=0; j<col; j++){
printf("%d ", *(matrix + i*col + j)); // or better: printf("%d ", *matrix++);
}
printf("\n");
}
}
int main(){
int matrix[2][3] = { {0, 1, 2}, {3, 4, 5} };
func(2, 3, matrix[0]);
return 0;
}
Internally, no matter how many dimensions an array has, C/C++ always maintains a 1D array. And so, we can pass any multi-dimensional array like this.
I don't know what you mean by "data dont get lost". Here's how you pass a normal 2D array to a function:
void myfunc(int arr[M][N]) { // M is optional, but N is required
..
}
int main() {
int somearr[M][N];
...
myfunc(somearr);
...
}
2D array:
int sum(int array[][COLS], int rows)
{
}
3D array:
int sum(int array[][B][C], int A)
{
}
4D array:
int sum(int array[][B][C][D], int A)
{
}
and nD array:
int sum(int ar[][B][C][D][E][F].....[N], int A)
{
}
I need to do this to persist operations on the matrix as well. Does that mean that it needs to be passed by reference?
Will this suffice?
void operate_on_matrix(char matrix[][20]);
C does not really have multi-dimensional arrays, but there are several ways to simulate them. The way to pass such arrays to a function depends on the way used to simulate the multiple dimensions:
1) Use an array of arrays. This can only be used if your array bounds are fully determined at compile time, or if your compiler supports VLA's:
#define ROWS 4
#define COLS 5
void func(int array[ROWS][COLS])
{
int i, j;
for (i=0; i<ROWS; i++)
{
for (j=0; j<COLS; j++)
{
array[i][j] = i*j;
}
}
}
void func_vla(int rows, int cols, int array[rows][cols])
{
int i, j;
for (i=0; i<rows; i++)
{
for (j=0; j<cols; j++)
{
array[i][j] = i*j;
}
}
}
int main()
{
int x[ROWS][COLS];
func(x);
func_vla(ROWS, COLS, x);
}
2) Use a (dynamically allocated) array of pointers to (dynamically allocated) arrays. This is used mostly when the array bounds are not known until runtime.
void func(int** array, int rows, int cols)
{
int i, j;
for (i=0; i<rows; i++)
{
for (j=0; j<cols; j++)
{
array[i][j] = i*j;
}
}
}
int main()
{
int rows, cols, i;
int **x;
/* obtain values for rows & cols */
/* allocate the array */
x = malloc(rows * sizeof *x);
for (i=0; i<rows; i++)
{
x[i] = malloc(cols * sizeof *x[i]);
}
/* use the array */
func(x, rows, cols);
/* deallocate the array */
for (i=0; i<rows; i++)
{
free(x[i]);
}
free(x);
}
3) Use a 1-dimensional array and fixup the indices. This can be used with both statically allocated (fixed-size) and dynamically allocated arrays:
void func(int* array, int rows, int cols)
{
int i, j;
for (i=0; i<rows; i++)
{
for (j=0; j<cols; j++)
{
array[i*cols+j]=i*j;
}
}
}
int main()
{
int rows, cols;
int *x;
/* obtain values for rows & cols */
/* allocate the array */
x = malloc(rows * cols * sizeof *x);
/* use the array */
func(x, rows, cols);
/* deallocate the array */
free(x);
}
4) Use a dynamically allocated VLA. One advantage of this over option 2 is that there is a single memory allocation; another is that less memory is needed because the array of pointers is not required.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
extern void func_vla(int rows, int cols, int array[rows][cols]);
extern void get_rows_cols(int *rows, int *cols);
extern void dump_array(const char *tag, int rows, int cols, int array[rows][cols]);
void func_vla(int rows, int cols, int array[rows][cols])
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
array[i][j] = (i + 1) * (j + 1);
}
}
}
int main(void)
{
int rows, cols;
get_rows_cols(&rows, &cols);
int (*array)[cols] = malloc(rows * cols * sizeof(array[0][0]));
/* error check omitted */
func_vla(rows, cols, array);
dump_array("After initialization", rows, cols, array);
free(array);
return 0;
}
void dump_array(const char *tag, int rows, int cols, int array[rows][cols])
{
printf("%s (%dx%d):\n", tag, rows, cols);
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
printf("%4d", array[i][j]);
putchar('\n');
}
}
void get_rows_cols(int *rows, int *cols)
{
srand(time(0)); // Only acceptable because it is called once
*rows = 5 + rand() % 10;
*cols = 3 + rand() % 12;
}
(See srand() — why call it only once?.)
Easiest Way in Passing A Variable-Length 2D Array
Most clean technique for both C & C++ is: pass 2D array like a 1D array, then use as 2D inside the function.
#include <stdio.h>
void func(int row, int col, int* matrix){
int i, j;
for(i=0; i<row; i++){
for(j=0; j<col; j++){
printf("%d ", *(matrix + i*col + j)); // or better: printf("%d ", *matrix++);
}
printf("\n");
}
}
int main(){
int matrix[2][3] = { {0, 1, 2}, {3, 4, 5} };
func(2, 3, matrix[0]);
return 0;
}
Internally, no matter how many dimensions an array has, C/C++ always maintains a 1D array. And so, we can pass any multi-dimensional array like this.
I don't know what you mean by "data dont get lost". Here's how you pass a normal 2D array to a function:
void myfunc(int arr[M][N]) { // M is optional, but N is required
..
}
int main() {
int somearr[M][N];
...
myfunc(somearr);
...
}
2D array:
int sum(int array[][COLS], int rows)
{
}
3D array:
int sum(int array[][B][C], int A)
{
}
4D array:
int sum(int array[][B][C][D], int A)
{
}
and nD array:
int sum(int ar[][B][C][D][E][F].....[N], int A)
{
}