Объявление двумерного массива неизвестного размера, C - PullRequest
4 голосов
/ 22 июня 2010

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

char        mValue[MAXROWS][MAXCOLUMNS]; 

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

Спасибо!

Ответы [ 6 ]

2 голосов
/ 22 июня 2010

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

ABCDE
FGHIJ   --->  ABCDEFGHIJKLMNO
KLMNO

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

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

2 голосов
/ 22 июня 2010

Как было предложено предыдущим постером, хороший способ - создать линейный массив и затем "преобразовать его в 2D".Во многих случаях кэширование 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;
1 голос
/ 22 июня 2010

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

#include <stdio.h>  /* For printf */

/* This is the bit that would go in a header, like char2darray.h */
#include <stdlib.h> /* For calloc */
#include <assert.h> /* 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;
}
1 голос
/ 22 июня 2010

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

char *p = malloc(ROWS * COLUMNS);

// To access x, y
// This is in row-major ordr
*(p + (x * COLUMNS) + y);
0 голосов
/ 27 июля 2017

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

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

//Declaration of mValues, undefined size:
std::vector< std::vector<char> > 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<char> 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 будет очень проблематичной, если производительность является проблемой.

0 голосов
/ 22 июня 2010

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

Соответствующий комп.Записи часто задаваемых вопросов по lang.c:

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