0

Я использовал переменный массив длину С, чтобы реализовать алгоритм:Как создать массив переменной длины в куче?

int matrix[rows][cols]; 

мне удалось проверить, что это не в состоянии за нелепые размеры. Есть ли способ выделить эту матрицу в куче вместо стека? В противном случае мне придется переписать это на int** ...

Нечто вроде calloc(sizeof(int[rows][cols]), 1)? Обратите внимание, что этот вопрос конкретно о массивах переменной длины.

+0

@ user3528438 Я спрашиваю ** конкретно ** о типе данных массива переменной длины. Кроме того, 5D, серьезно? –

+4

Что работает для 5D, можно свести к работе для 2D. Вы пробовали 'calloc (sizeof (int [rows] [cols]), 1)'? Какой размер вы получили? На самом деле более актуальным является печать значений 'rows',' cols' и выражения 'sizeof'. Он дает вам то, что вам нужно? Возникает вопрос «Что мне назначить результат»? –

+0

@ TomášZato 5D? Да серьезно! Почему нет? –

ответ

2

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

#include <stdlib.h> 
#include <stdio.h> 

static void print_matrix(int r, int c, int matrix[r][c]) 
{ 
    for (int i = 0; i < r; i++) 
    { 
     for (int j = 0; j < c; j++) 
      printf(" %d", matrix[i][j]); 
     putchar('\n'); 
    } 
} 

static void set_matrix(int r, int c, int matrix[r][c]) 
{ 
    for (int i = 0; i < r; i++) 
    { 
     for (int j = 0; j < c; j++) 
      matrix[i][j] = (i+1) * 100 + j + 1; 
    } 
} 

int main(void) 
{ 
    size_t rows = 9; 
    size_t cols = 7; 
    size_t size = sizeof(int[rows][cols]); 
    printf("rows = %zu, cols = %zu, size = %zu\n", rows, cols, size); 
    int (*matrix)[cols] = calloc(sizeof(int[rows][cols]), 1); 
    if (matrix != 0) 
    { 
     set_matrix(rows, cols, matrix); 
     print_matrix(rows, cols, matrix); 
     free(matrix); 
    } 
    return 0; 
} 

Этот код тщательно использует calloc() к нулю всех элементов массива, а затем вызывает set_matrix() установить их ненулевые значения. Как написано, malloc() будет лучше, чем calloc(), но вопрос был использован calloc(), и было бы непросто сделать его разумным для использования с этим кодом (например, условное назначение в set_matrix(), например if (i && j && i != j)).

Пример вывода:

rows = 9, cols = 7, size = 252 
101 102 103 104 105 106 107 
201 202 203 204 205 206 207 
301 302 303 304 305 306 307 
401 402 403 404 405 406 407 
501 502 503 504 505 506 507 
601 602 603 604 605 606 607 
701 702 703 704 705 706 707 
801 802 803 804 805 806 807 
901 902 903 904 905 906 907 
1

Вы можете создать указатель на VLA:

size_t rows, cols; 
... // get values for rows and cols 
T (*arr)[cols] = malloc(sizeof (T [cols]) * rows); 
if (arr) 
{ 
    ... 
    arr[i][j] = some_value; 
    ... 
} 

Существует некоторая дискуссия по поводу того,

T (*arr)[cols] = malloc(sizeof *arr * rows); 

должен работать. Образом стандарт сформулирован, эта форма приводит к неопределенному поведению, так как sizeof должно оценить *arr во время выполнения (так как выражения*arr относятся к VLA) и arr является недействительным, когда указателем sizeof *arr оценивается.

Однако это зависит от того, что означает «оценка» в этом конкретном контексте; нет никаких причин, чтобы иметь в разыменоватьarr для того, чтобы определить размер массива он указует, больше, чем вы бы для массива фиксированной длины:

T (*arr)[10] = malloc(sizeof *arr * rows); 

Я и несколько других из мнение, что стандарт плохо сформулирован в этом отношении и что sizeof *arr должен быть действительным, если arr указывает на фиксированный-или массив переменной длины. Это идиома, которую я использую, и это не сработало на мне ... еще.

Но я был бы умен, если бы не указал на эту проблему, и предоставил вам то, что знаю не будет результат UB.

Смежные вопросы