|
Программирование >> Перегруженные имена функций и идентификаторы
должен быть включен (а для массивов размерности 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);
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |