В языке "C" предусмотрены прямоугольные многомерные мас-сивы, хотя на практике существует тенденция к их значительноболее редкому использованию по сравнению с массивами указа-телей. В этом разделе мы рассмотрим некоторые их свойства. Рассмотрим задачу преобразования дня месяца в день годаи наоборот. Например, 1-ое марта является 60-м днем невисо-косного года и 61-м днем високосного года. Давайте введемдве функции для выполнения этих преобразований: DAY_OF_YEARпреобразует месяц и день в день года, а MONTH_DAY преобразу-ет день года в месяц и день. Так как эта последняя функциявозвращает два значения, то аргументы месяца и дня должныбыть указателями: MONTH_DAY(1977, 60, &M, &D) Полагает M равным 3 и D равным 1 (1-ое марта). Обе эти функции нуждаются в одной и той же информацион-ной таблице, указывающей число дней в каждом месяце. Так какчисло дней в месяце в високосном и в невисокосном году отли-чается, то проще представить их в виде двух строк двумерногомассива, чем пытаться прослеживать во время вычислений, чтоименно происходит в феврале. Вот этот массив и выполняющиеэти преобразования функции: STATIC INT DAY_TAB[2][13] = { (0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31), (0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)}; DAY_OF_YEAR(YEAR, MONTH, DAY) /* SET DAY OF YEAR */INT YEAR, MONTH, DAY; /* FROM MONTH & DAY */{ INT I, LEAP; LEAP = YEAR%4 == 0 && YEAR%100 != 0 \!\! YEAR%400 == 0; FOR (I = 1; I < MONTH; I++) DAY += DAY_TAB[LEAP][I]; RETURN(DAY);{ MONTH_DAY(YEAR, YEARDAY, PMONTH, PDAY) /*SET MONTH,DAY */INT YEAR, YEARDAY, *PMONTH, *PDAY; /* FROM DAY OF YEAR */{ LEAP = YEAR%4 == 0 && YEAR%100 != 0 \!\! YEAR%400 == 0; FOR (I = 1; YEARDAY > DAY_TAB[LEAP][I]; I++)YEARDAY -= DAY_TAB[LEAP][I]; *PMONTH = I; *PDAY = YEARDAY;} Массив DAY_TAB должен быть внешним как для DAY_OF_YEAR, таки для MONTH_DAY, поскольку он используется обеими этими фун-кциями. Массив DAY_TAB является первым двумерным массивом, с ко-торым мы имеем дело. По определению в "C" двумерный массивпо существу является одномерным массивом, каждый элемент ко-торого является массивом. Поэтому индексы записываются как DAY_TAB[I][J]а неDAY_TAB [I, J] как в большинстве языков. В остальном с двумерными массивамиможно в основном обращаться таким же образом, как в другихязыках. Элементы хранятся по строкам, т.е. При обращении кэлементам в порядке их размещения в памяти быстрее всего из-меняется самый правый индекс. Массив инициализируется с помощью списка начальных зна-чений, заключенных в фигурные скобки; каждая строка двумер-ного массива инициализируется соответствующим подсписком. Мыпоместили в начало массива DAY_TAB столбец из нулей для то-го, чтобы номера месяцев изменялись естественным образом от1 до 12, а не от 0 до 11. Так как за экономию памяти у наспока не награждают, такой способ проще, чем подгонка индек-сов. Если двумерный массив передается функции, то описаниесоответствующего аргумента функции должно содержать количес-тво столбцов; количество строк несущественно, поскольку, каки прежде, фактически передается указатель. В нашем конкрет-ном случае это указатель объектов, являющихся массивами из 13 чисел типа INT. Таким образом, если бы требовалось пере-дать массив DAY_TAB функции F, то описание в F имело бы вид: F(DAY_TAB)INT DAY_TAB[2][13];{ ...} Так как количество строк является несущественным, то описа-ние аргумента в F могло бы быть таким: INT DAY_TAB[][13]; или таким INT (*DAY_TAB)[13]; в которм говорится, что аргумент является указателем массиваиз 13 целых. Круглые скобки здесь необходимы, потому чтоквадратные скобки [] имеют более высокий уровень старшинст-ва, чем *; как мы увидим в следующем разделе, без круглыхскобок INT *DAY_TAB[13]; является описанием массива из 13 указателей на целые.