Передача 2D-массива в функцию в C - PullRequest
0 голосов
/ 13 февраля 2011

По сути, у меня есть матрица данных (скажем, целых), которую я хотел бы сохранить в двумерном массиве, в котором измерения неизвестны до времени выполнения (например, x столбцов и y строк).Я хочу заполнить массив в функции, поэтому я предполагаю, что мне нужно сделать что-то вроде этого:

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
        }
    }
}

Очевидно, что это не работает, но я не уверен, как сделать то, что яточно описывая.

Ответы [ 4 ]

4 голосов
/ 13 февраля 2011

Чего вам не хватает, так это того, что каждый из внутренних массивов тоже должен быть malloc'ом.

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

должно быть примерно таким:Библиотеки матриц, о которых я знаю, будут просто использовать:

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

, а затем использовать:

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

для чтения отдельных элементов.Для (не разреженных) матриц это более эффективно, чем наличие отдельно выделенного блока для каждой строки.Это также гарантирует непрерывность данных в памяти, что может повысить эффективность кэширования процессора.

0 голосов
/ 13 февраля 2011

C99 имеет простой инструмент, который часто не одобряется, но служит именно тем, что вы хотите, массивами переменной длины, VLA.

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

Причина, по которой они осуждаются, заключается в том, что если вы используете их напрямую для размещения матриц в стеке, вы можете наблюдать переполнение стека. Вы можете избежать этого, фактически передав указатели таким зверям:

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

и в некоторых функциях:

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

Для синтаксиса вам просто нужно, чтобы размер измерений был указан перед матрицей в списке параметров, чтобы они были известны в этой точке. Также используйте size_t для всего, что является индексами и размерами объектов, обычно нет смысла иметь для них подписанный тип.

0 голосов
/ 13 февраля 2011
Матрица

в main - это указатель на указатель на int.Ваша программа выделяет место для x указателей на int.Учитывая цикл в populateMatrix, это должно быть пространство для указателей y на int.Что еще более важно, вы не выделили место для строк.Вам нужен еще один цикл в main, который будет выделять y строк, каждый из которых будет достаточно большим, чтобы вместить x int.

0 голосов
/ 13 февраля 2011

Разве вы не можете просто использовать одномерный массив и хранить по строкам или столбцам?Тогда вы просто получите доступ к элементам массива, используя array[row * numcols + col] вместо array[row][col].

Это на самом деле не имеет никакого значения, так как памяти не важно, используете ли вы два измерения или одно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...