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()), но много от другите въпроси са уместни. Има и много тясно свързани въпроси -- възможни дубликати -- изброени в списъка „свързани въпроси” в RHS на страницата. - 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