Опубликован: 05.07.2006 | Доступ: свободный | Студентов: 4679 / 885 | Оценка: 4.12 / 3.74 | Длительность: 18:59:00
Лекция 6:

Указатели и массивы

5.9. Инициализация массивов указателей

Рассмотрим задачу написания функции month_name(n), которая возвращает указатель на символьную строку, содержащую имя n -го месяца. Это идеальная задача для применения внутреннего статического массива. функция month_name содержит локальный массив символьных строк и при обращении к ней возвращает указатель нужной строки. Тема настоящего раздела - как инициализировать этот массив имен.

char *month_name(n) /* return name of n-th month */
int n;
{
 static char *name[] = {
    "illegal month",
    "january",
    "february",
    "march",
    "april",
    "may",
    "jun",
    "july",
    "august",
    "september",
    "october",
    "november",
    "december"
 };
     return ((n < 1 || n > 12) ? name[0] : name[n]);
}

описание массива указателей на символы name точно такое же, как аналогичное описание lineptr в примере с сортировкой. Инициализатором является просто список символьных строк ; каждая строка присваивается соответствующей позиции в массиве. Более точно, символы i -ой строки помещаются в какое-то иное место, а ее указатель хранится в name[i]. Поскольку размер массива name не указан, компилятор сам подсчитывает количество инициализаторов и соответственно устанавливает правильное число.

5.10. Указатели и многомерные массивы

Начинающие изучать язык "с" иногда становятся в тупик перед вопросом о различии между двумерным массивом и массивом указателей, таким как name в приведенном выше примере. Если имеются описания

int a[10][10]; int *b[10];

то a и b можно использовать сходным образом в том смысле, что как a[5][5], так и b[5][5] являются законными ссылками на отдельное число типа int. Но a - настоящий массив: под него отводится 100 ячеек памяти и для нахождения любого указанного элемента проводятся обычные вычисления с прямоугольными индексами. Для b, однако, описание выделяет только 10 указателей ; каждый указатель должен быть установлен так, чтобы он указывал на массив целых. Если предположить, что каждый из них указывает на массив из 10 элементов, то тогда где-то будет отведено 100 ячеек памяти плюс еще десять ячеек для указателей. Таким образом, массив указателей использует несколько больший объем памяти и может требовать наличие явного шага инициализации. Но при этом возникают два преимущества: доступ к элементу осуществляется косвенно через указатель, а не посредством умножения и сложения, и строки массива могут иметь различные длины. Это означает, что каждый элемент b не должен обязательно указывать на вектор из 10 элементов; некоторые могут указывать на вектор из двух элементов, другие - из двадцати, а третьи могут вообще ни на что не указывать.

Хотя мы вели это обсуждение в терминах целых, несомненно, чаще всего массивы указателей используются так, как мы продемонстрировали на функции month_name, - для хранения символьных строк различной длины.

Упражнение 5-6

Перепишите функции day_of_year и month_day, используя вместо индексации указатели.