Вы выделили массив для rows
размером cols
, но компилятор не может узнать фактический размер строки для каждой строки, поэтому запись entries[i]
действительно ожидает указатель на простой массив плавает, а не двумерный массив. Это одно из основных отличий в структуре от n-мерного массива и массивов указателей в C. Компилятор знает, как его измерять, только когда вы полностью определите размеры массива (например, когда вы объявляете его как float entries[N][M];
--- посмотрите, что вы не можете использовать переменные выражения в измерениях, только статические константы времени компиляции)
У вас есть два подхода:
Использование одного массива измерений для вычисления индекса на основе размеров строк:
typedef struct matrix matrix;
struct matrix {
unsigned int n_rows;
unsigned int n_cols;
float *entries; /* we make this to point to a single array of n_rows * n_cols entries */
};
new->entries = malloc(n_rows * n_cols * sizeof(float));
new->n_rows=n_rows;
new->n_cols=n_cols;
for(int x = 0; x < n_rows; x++){
for(int y = 0; y < n_cols; y++){
new->entries[x * n_cols + y] = 0.0; /* entry position should be as shown */
}
Использовать отдельные массивы строк из n_cols
записей (это уже было показано в другом ответе @joel)
typedef struct matrix matrix;
struct matrix {
unsigned int n_rows;
unsigned int n_cols;
float **entries; /* this time the entries field points to an array of pointers to float. */
};
new->entries = malloc(n_rows * sizeof *new->entries); /* individual cells are 'float *', not 'float' this time. */
new->n_rows=n_rows;
new->n_cols=n_cols;
for(int x = 0; x < n_rows; x++){
new->entries[x] = malloc(n_cols* sizeof **new->entries); /* this time float *'s are here */
for(int y = 0; y < n_cols; y++){
new->entries[x][y] = 0; /* entry position should be as shown */
}
}
Оба метода имеют замечания:
Первый метод требует только один malloc(3)
для массива entry, так что это упрощает распределение и освобождение, но некоторые реализации могут ограничивать фактический размер одного malloc(3)
в случае, если вы хотите выделить огромные матрицы , Это также облегчает освобождение всей матрицы.
Второй метод требует только malloc из n_rows
указателей и n_rows
malloc из n_cols
float
s. Это позволит выделить огромные матрицы (вы никогда не выделите всю матрицу в одном фрагменте), но вам придется сначала освободить все строки, а затем массив указателей на строки, прежде чем освобождать структуру матрицы.
Я рекомендую вам использовать malloc(n_cols * sizeof *new->entries)
вместо malloc(n_cols * sizeof (float *))
, поэтому вам не нужно менять это выражение в случае, если вы измените тип определения new->entries
.
Наконец, подумайте, что в языке C нет магии в отношении вызова функций. Вы, вероятно, ошибочно предположили, что создание malloc( n_rows * n_cols * sizeof(float) )
автоматически преобразует указатель в двумерный массив , но в этом нет ничего волшебного, malloc(3)
- это обычная функция C, подобная той, которую вы можете написать, и именно поэтому требуется фактическое количество байтов, а не размеры (в элементах) массива.