Ответ 1
Несколько вещей, чтобы указать.
Прежде всего, вы не можете назначить объект массива, как вы здесь:
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);
Для 2-мерных массивов это немного уродливее:
void foo (T (*p)[M]) {...}
...
T arr[N][M];
foo(arr);
Это также зависит от того, что M известно во время компиляции, что ограничивает полезность функции. То, что вам нужно, это функция, которая может работать с 2-мерным массивом произвольного размера. Лучший способ, которым я это знаю, - это не передавать указатель на массив, передавать адрес первого элемента в массиве [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 *
), а второй - на указатель на 2-й массив char (char (*)[HEIGHT]
).