Несколько вещей, на которые стоит обратить внимание.
Прежде всего, вы не можете назначить объект массива, как здесь:
char A[WIDTH][HEIGHT];
A=rand_grid(WIDTH,HEIGHT);
Объекты типа массива не могут быть изменены.
Во-вторых, функции в C не могут возвращать типы массивов. Они могут возвращать указатели в массивы, хотя:
char (*foo(int width))[HEIGHT]
{
/**
* dynamically allocate memory for a widthxHEIGHT array of char
*/
char (*newArr)[HEIGHT] = malloc(sizeof *newArr * width);
/**
* initialize array contents here
*/
return newArr;
}
Синтаксис немного сбивает с толку; это читается как
foo -- foo
foo(int width) -- is a function
-- taking an int parameter
*foo(int width) -- returning a pointer
(*foo(int width))[HEIGHT] -- to a HEIGHT-element array
char (*foo(int width))[HEIGHT] -- of char
Для C89 HEIGHT в приведенном выше фрагменте должен быть интегральным выражением постоянной времени компиляции (или макрос, числовой литерал или арифметическое выражение, состоящее из макросов и / или числовых литералов). Я не уверен, верно ли это и для C99.
Основываясь на опубликованном вами фрагменте, вам нужно взять уже выделенный массив и инициализировать его содержимое. Помните, что в большинстве случаев выражение типа массива будет неявно преобразовано в указатель на базовый тип. IOW, если вы передаете N-элементный массив T в функцию, то, что функция фактически получает, это указатель на T:
void foo (T *p) {...}
...
T arr[N];
foo(arr);
Для двумерных массивов это немного страшнее:
void foo (T (*p)[M]) {...}
...
T arr[N][M];
foo(arr);
Это также зависит от того, что M известно во время компиляции, что ограничивает полезность функции. Вам нужна функция, которая может работать с двумерным массивом произвольного размера. Лучший из известных мне способов достижения этой цели - вместо передачи указателя на массив передать адрес первого элемента в массиве [1] и передать число строк и столбцов в виде отдельных параметров:
void foo(T *base, size_t rows, size_t cols) {...}
...
T arr[N][M];
foo (&arr[0][0], N, M);
Итак, ваша функция rand_grid будет выглядеть примерно так:
void rand_grid(char *base, size_t rows, size_t cols)
{
size_t i, j;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
/**
* Since base is a simple char *, we must index it
* as though it points to a 1-d array. This works if
* base points to the first element of a 2-d array,
* since multi-dimensional arrays are contiguous.
*/
base[i*cols+j] = initial_value();
}
}
}
int main(void)
{
char A[WIDTH][HEIGHT];
rand_grid(&A[0][0], WIDTH, HEIGHT);
...
}
- Даже если выражения
&A[0][0]
и A
дают одно и то же значение (базовый адрес A), типы этих двух выражений различны. Первое выражение оценивается как простой указатель на char (char *
), а второе - как указатель на двумерный массив char (char (*)[HEIGHT]
).