Программирование >>  Перегруженные имена функций и идентификаторы 

1 ... 177 178 179 [ 180 ] 181 182 183 ... 210


должен быть включен (а для массивов размерности 3 и больше, все промежуточные размеры).

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

Как писать функции, принимающие в качестве параметра двумерные массивы, ширина которых во время компиляции неизвестна?

Это непросто. Один из путей - передать указатель на элемент [0][0] вместе с размерами и затем симулировать индексацию вручную :

f2(aryp, nrows, ncolumns) int *aryp;

int nrows, ncolumns;

{ ... array[i][j] это aryp[i * ncolumns + j] ... }

Этой функции массив может быть передан так:

f2(&array[0][0], NROWS, NCOLUMNS);

Нужно, однако, заметить, что программа,выполняющая индексирование многомерного массива вручную не полностью соответствует стандарту ANSI C; поведение (&array[0][0])[x] не определено при x > NcOLUMNS.

gcc разрешает объявлять локальные массивы, которые имеют размеры, задаваемые аргументами функции, но это - нестандартное расширение.

Как объявить указатель на массив?

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

Вместо указателя на массив рассмотрим использование указателя на один из элементов массива. Массивы типа T превращаются в указатели типа Т, что удобно; индексация ии увеличение указателя позволяет иметь доступ к отдельным элементам массива. Истинные указатели на массивы при увеличении или индексации указывают на следующий массив и в общем случае если и полезны, то лишь при операциях с массивами массивов.

Если действительно нужно объявить указатель на целый массив, используйте что-то вроде int (*ap)[N]; где N - размер массива. Если размер массива неизвестен, параметр N может быть



опущен, но получившийся в результате тип указатель на массив неизвестного размера - бесполезен.

Исходя из того, что ссылки на массив превращаются в указатели, скажите в чем разница для массива int array[NROWS][NCOLUMNS]; между array и &array?

Согласно ANSI/ISO стандарту Си, &array дает указатель типа указатель-на-массив-Т , на весь массив.

В языке Си до выхода стандарта ANSI оператор & в &array игнорировался, порождая предупреждение компилятора. Все компиляторы Си, встречая просто имя массива, порождают указатель типа указатель-на-Т, т.е. на первый элемент массива.

Как динамически выделить память для многомерного массива?

Лучше всего в1делить память для массива указателей, а затем инициализировать каждый указатель так, чтобы он указывал на динамически создаваемую строку. Вот пример для двумерного массива:

int **array1 = (int **)malloc(nrows * sizeof(int *)); for(i = 0; i < nrows;

array1[i] = (int *)malloc(ncolumns * sizeof(int)); (В реальной программе, malloc должна быть правильно объявлена, а каждое возвращаемое malloc значение - проверено.)

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

int **array2 = (int **)malloc(nrows * sizeof(int *));

array2[0] = (int *)malloc(nrows * ncolumns * sizeof(int));

for(i = 1; i < nrows; i++) array2[i] = array2[0] + i * ncolumns; В любом случае доступ к элементам динамически задаваемого массива может быть произведен с помощью обычной индексации: array[i][j].

Если двойная косвенная адресация, присутствующая в приведенных выше примерах, вас по каким-то причинам не устраивает, можно имитировать двумерный массив с помощью динамически задаваемого одномерного массива:

int *array3 = (int *)malloc(nrows * ncolumns * sizeof(int));



Теперь, однако, операции индексирования нужно выполнять вручную, осуществляя доступ к элементу i,j с помощью array3[i*ncolumns+j]. (Реальные вычисления можно скрыть в макросе, однако вызов макроса требует круглых скобок и запятых, которые не выглядят в точности так, как индексы многомерного массива.)

Наконец, можно использовать указатели на массивы:

int (*array4)[NCOLUMNS] = (int(*)[NCOLUMNS])malloc(nrows * sizeof(*array4));, но синтаксис становится устрашающим, и всего лишь одно измерение должно быть известно во время компиляции.

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

Как мне равноправно использовать статически и динамически задаваемые многомерные массивы при передаче их в качестве параметров функциям?

Идеального решения не существует. Возьмем объявления

int array[NROWS][NCOLUMNS];

int **array1; int **array2; int *array3;

int (*array4)[NCOLUMNS]; соответствующие способам выделения памяти и функции, объявленные как:

f1(int a[][NCOLUMNS], int m, int n);

f2(int *aryp, int nrows, int ncolumns); f3(int **pp, int m, int n);

Тогда следующие вызовы должны работать так, как ожидается:

f1(array, NROWS, NCOLUMNS); f1(array4, nrows, NCOLUMNS);

f2(&array[0][0], NROWS, NCOLUMNS); f2(*array2, nrows, ncolumns); f2(array3, nrows, ncolumns);

f2(*array4, nrows, NCOLUMNS);

f3(array1, nrows, ncolumns);



1 ... 177 178 179 [ 180 ] 181 182 183 ... 210

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика