Объявление двумерного массива неизвестного размера, C

У меня есть массив, объявленный как член структуры в C. Массив объявляется как:

char mValue[MAXROWS][MAXCOLUMNS]; 

где MAXROWS и MAXROWS – 300. Есть ли лучший способ сделать это? Я имею в виду, следует ли объявлять их как указатели?

Спасибо!

Как предложил предыдущий плакат, хорошим способом является создание линейного массива, а затем «преобразование его в 2D». Много раз кеширование двумерных указателей значительно увеличивает скорость программ, которые используют этот массив, например:

 mystruct *p = (mystruct*)calloc(ROWS * COLUMNS, sizeof(mystruct)); mystruct **p2 = (mystruct**)calloc(ROWS, sizeof(mystruct*)); for (int i = 0; i < ROWS; i++) p2[i] = p + i*COLUMNS; 

Затем вы можете просто получить доступ к 2D-элементу:

 p2[row][column] = foo; 

Если все ваши ряды имеют одинаковый размер, вы должны использовать 1D-массив со строками, хранящимися последовательно:

 ABCDE FGHIJ ---> ABCDEFGHIJKLMNO KLMNO 

Элемент в строке i , столбец j будет иметь индекс i * ROW_LENGTH + j в массиве 1D.

Вы можете выделить массив, используя malloc(ROW_LENGTH * NUM_ROWS) .

Другой способ – создать линейный массив, а затем преобразовать его в 2d:

 char *p = malloc(ROWS * COLUMNS); // To access x, y // This is in row-major ordr *(p + (x * COLUMNS) + y); 

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

 #include  /* For printf */ /* This is the bit that would go in a header, like char2darray.h */ #include  /* For calloc */ #include  /* For assert */ struct Char2DArray { int rows; int columns; char *values; }; /* This is the bit that would go in a source file, like char2darray.c */ void C2DA_initialize(struct Char2DArray *array, int rows, int columns) { assert(array != 0); array->values = calloc(rows * columns, sizeof(char)); array->rows = rows; array->columns = columns; } void C2DA_set(struct Char2DArray *array, int row, int column, int value) { assert(array != 0); assert(array->values != 0); assert(row < array->rows); assert(row >= 0); assert(column < array->columns); assert(column >= 0); array->values[(row * array->rows) + column] = value; } char C2DA_get(struct Char2DArray *array, int row, int column) { assert(array != 0); assert(array->values != 0); assert(row < array->rows); assert(row >= 0); assert(column < array->columns); assert(column >= 0); return array->values[(row * array->rows) + column]; } void C2DA_free(struct Char2DArray *array) { free(array->values); array->values = 0; } /* Here's a main.c to use it */ int main() { struct Char2DArray a; C2DA_initialize(&a, 16, 16); unsigned char c = 0; int x, y; for (x=0; x<16; x++) { for (y=0; y<16; y++) { C2DA_set(&a, x, y, (char)c); c++; } } printf("Character with hex value 0x55 is %c\n", C2DA_get(&a, 5, 5)); C2DA_free(&a); return 0; } 

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

Соответствующие записи в comp.lang.c:

  • Я натолкнулся на какой-то код, который объявил такую ​​структуру …
  • Как я могу динамически распределять multidimensional array?

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

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

 //Declaration of mValues, undefined size: std::vector< std::vector > mValues; //Filling of mValues: int max_x = 100 ; int max_y = 100 ; char char_foo = 'a'; for ( int x = 0; x <= max_x; ++x ) { vector temp; for ( int y = 0; y <= max_y; ++y ) { temp.push_back( char_foo ); } mValues.push_back( temp ); } // Referencing with familiar index notation: mValues[a][b]; //The a-th row's b-th element 

Если вы боретесь с массивами, но сильно желаете знакомый язык индексирования, я нашел, что это хорошая альтернатива.

Обратите внимание, что порядок индексирования A тогда B будет критическим для использования памяти при вызове этих данных. Несоблюдение информации в порядке A, B будет очень проблематичным, если производительность будет проблемой.