C — передать указатель на двумерный массив в функцию

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

int function(int (*grid)[][], int height, int width);

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

(Небольшое пояснение: ширина и высота сетки определяются #define в файле main.c, а нужный мне прототип функции находится в заголовочном файле, поэтому он не может получить доступ к этому #define...)

Спасибо


person Magix    schedule 12.07.2014    source источник
comment
Здесь: stackoverflow.com/questions/8767166/   -  person Bruno Monteiro    schedule 12.07.2014


Ответы (2)


Если вы не используете MS Visual Studio 2013 Express, как я, а также у вас нет компилятора, совместимого со стандартом C99, вы можете сделать следующее:

int function( int height, int width, int (*grid)[height][width] );

Все, что вам нужно, — это функциональность массивов переменной длины (VLA), которой нет в полусовместимом MSVC. Вот пример его использования: http://ideone.com/J3y2oi

person Utkan Gezer    schedule 12.07.2014
comment
Это работает! Но я никогда не слышал о функциональности VLA, у вас есть документы/ссылки на эту тему? это было бы здорово :) спасибо - person Magix; 12.07.2014
comment
Вы можете открыть окно поиска в верхней части страницы и ввести «[c] variable length array». Самый первый вопрос в списке на самом деле не очень актуален (в нем подробно описывается небольшая, но важная проблема как часть ответа о sizeof()), но многие другие вопросы имеют значение. Есть также много тесно связанных вопросов — возможных дубликатов — перечисленных в списке «связанных вопросов» в правой части страницы. - person Jonathan Leffler; 12.07.2014

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

Если вы застряли с компилятором C89, вам придется работать еще усерднее. Безусловно, самое простое решение — сделать #define измерения доступными в заголовке; тогда вы можете написать:

int function(grid[HEIGHT][WIDTH]) { ... }
int function(grid[][WIDTH]) { ... }

Если вы не можете этого сделать, вам придется подумать об изменении либо кода в функции, либо структур данных в main.c.

Изменение функции означает:

int function(int height, int width, int *grid)
{
    int i, j;
    for (i = 0; i < height; i++)
        for (j = 0; j < width; j++)
            grid[i*width + j] = 0;
    return j;
}

Это берет обычный указатель на-int и явно выполняет вычисления индекса, а не просто записывает два индекса. Ваш основной код может иметь:

int grid[HEIGHT][WIDTH];

i = function(HEIGHT, WIDTH, &grid[0][0]);

В качестве альтернативы вы создаете вторичную структуру, набор указателей на указатели, в main():

int grid_rows[HEIGHT];
for (i = 0; i < HEIGHT; i++)
    grid_row[i] = grid[i];

i = function(HEIGHT, WIDTH, grid_rows);

Теперь определение такое:

int function(int height, int width, int **grid)
{
    int i, j;
    for (i = 0; i < height; i++)
        for (j = 0; j < width; j++)
            grid[i][j] = 0;
    return j;
}

Это восстанавливает удобство записи в функции за счет дополнительной памяти и инициализации.

person Jonathan Leffler    schedule 12.07.2014