简体   繁体   中英

Passing a 2D array to a function in C

I have, essentially, a matrix of data (lets say ints) that I would like to store in a 2D array in which the dimensions are not known until runtime (say x columns and y rows). I want to populate the array in a function, so I assume I need to do something like this:

int main(int argc, char **argv) {
    int y = atoi(argv[1]);
    int x = atoi(argv[2]);
    int **matrix = malloc(x * sizeof(int*));
    populateMatrix(matrix, y, x);
    return 0;
}

void populateMatrix(**matrix, int y, int x) {
    int i, j;
    for (i = 0; i < y; i++) {
        for (j = 0; j < x; j++) {
            matrix[i][j] = i * j; // populated with trivial data to keep it simple
        }
    }
}

Obviously this doesn't work, but I'm not sure how to do what I'm describing exactly.

What you're missing is that each of the inner arrays needs to be malloc'ed too.

int **matrix = malloc(x * sizeof(int *));

should be something like:

int **matrix = (int **)malloc(y * sizeof(int *));
for (i = 0; i < y; ++i) {
    matrix[i] = (int *)malloc(x * sizeof(int));
}

That said, most matrix libraries I'm aware of would just use:

int *matrix = (int *)malloc(x * y * sizeof(int));

and then use:

int n = matrix[y * cols + x];

to read the individual elements. For (non-sparse) matrices this is more efficent than having a separately allocated block for each row. It also guarantees that the data is contiguous in memory which can make CPU caches more effective.

Can you not just use a one-dimensional array and store by rows or columns? Then you would just access the array elements using array[row * numcols + col] instead of array[row][col] .

It really doesn't make any difference internally, as the memory doesn't care if you use two dimensions or one.

matrix in main is a pointer to a pointer to int. Your program allocates space for x pointers to int. Considering the loop in populateMatrix, that should be space for y pointers to int. More importantly, you have not allocated space for the rows. You need another loop in main that will allocate y rows each large enough to hold x ints.

C99 has a simple tool that is often frowned upon but serves exactly what you want, variable length arrays, VLA.

void populateMatrix(size_t y, size_t x, double matrix[x][y]);

The reason why they are frowned upon is that if you use them directly to allocate matrices on the stack you might observe stack overflow. You can avoid that by actually passing pointers to such beasts:

void populateMatrix2(size_t y, size_t x, double (*matrix)[x][y]) {
  for (... something ...) {
     (*matrix)[i][j] = 33.0;
  }
}

and in some function:

double (*myMatrix)[n][m] = malloc(sizeof(*myMatrix));
populateMatrix2(n, m, myMatrix);

For the syntax, you just have to have the size of the dimensions come before the matrix in the parameter list such that they are known at that point. Also use size_t for everything that is indices and sizes of objects, it makes usually no sense to have a signed type for them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM