netlib.narod.ru | < Назад | Оглавление | Далее > |
Начинающие программировать на Си иногда не понимают, в чем разница между двумерным массивом и массивом указателей вроде name из приведенного примера. Для двух следующих определений:
int a[10][20]; int *b[10];
записи a[3][4] и b[3][4] будут синтаксически правильным обращением к некоторому значению типа int. Однако только a является классическим двумерным массивом: для двухсот элементов типа int будет выделена память, а вычисление смещения элемента a[строка][столбец] от начала массива будет вестись по формуле 20 * строка + столбец, учитывающей его прямоугольную природу. Для b же определено только 10 указателей, причем без инициализации. Инициализация должна задаваться явно — либо статически, либо в программе. Предположим, что каждый элемент b указывает на массив из 20 элементов, в результате где-то будет выделено пространство, в котором разместятся 200 значений типа int, и еще 10 ячеек будет выделено для указателей. Важное преимущество массива указателей в том, что строки такого массива могут иметь разные длины. Таким образом, каждый элемент массива b не обязательно указывает на массив из 20 элементов; один может указывать на два элемента, другой — на пятьдесят, а некоторые и вовсе могут ни на что не указывать.
Наши рассуждения здесь касались целых значений, однако чаще массивы указателей используются для работы со строками символов, различающимися по длине, как это было в функции month_name. Сравните определение массива указателей и соответствующий ему рисунок:
char *name[] = { "Неправильный месяц", "Январь", "Февраль", "Март" };
с объявлением и рисунком для двумерного массива:
char aname[][20] = { "Неправильный месяц", "Январь", "Февраль", "Март" };
Упражнение 5-9 |
Перепишите программы day_of_year и month_day, используя вместо индексов указатели. |
netlib.narod.ru | < Назад | Оглавление | Далее > |