Месяц 1 имеет 31 дней.
Месяц 2 имеет 28 дней.
Месяц 3 имеет 31 дней.
Месяц 4 имеет 30 дней.
Месяц 5 имеет 31 дней.
Месяц 6 имеет 30 дней.
Месяц 7 имеет 31 дней.
Месяц 8 имеет 31 дней.
Месяц 9 имеет 30 дней.
Месяц 10 имеет 31 дней.
Ну вот, теперь мы получаем точно 10 значений. Наш метод, позволяющий программе самой находить размер массива, не позволил нам напечатать конец массива.
Существует и более короткий способ инициализации массивов, но поскольку он применим только к символьным строкам, мы рассмотрим его в следующей главе.
В заключение мы покажем, что можно присваивать значения элементам массива, относящегося к любому классу памяти. Например, в приведенном ниже фрагменте программы присваиваются четные числа элементам автоматического массива:
/* присваивание значений массиву */
main( )
{
int counter, evens [50];
for(counter = 0; counter < 50; counter++)
evens[counter] = 2 * counter;
...
}
Как было сказано в гл. 9, указатели позволяют нам работать с символическими адресами. Поскольку в реализуемых аппаратно командах вычислительной машины интенсивно используются адреса, указатели предоставляют возможность применять адреса примерно так, как это делается в самой машине, и тем самым повышать эффективность программ. В частности, указатели позволяют эффективно организовать работу с массивами. Действительно, как мы могли убедиться, наше обозначение массива представляет собой просто скрытую форму использования указателей.
Например, имя массива определяет также его первый элемент, т. е. если flizny[]- массив, то
flizny == &flizny[0]
и обе части равенства определяют адрес первого элемента массива. (Вспомним, что операция &выдает адрес.) Оба обозначения являются константами типа указатель, поскольку они не изменяются на протяжении всей программы. Однако их можно присваивать (как значения) переменной типа указатель и изменять значение переменной, как показано в ниже следующем примере. Посмотрите, что происходит со значением указателя, если к нему прибавить число.
/* прибавление к указателю */
main( )
{
int dates[4], *pti, index;
float bills [4], *ptf;
pti = dates; /* присваивает адрес указателю массива */
ptf = bills;
for(index = 0; index < 4; index++)
printf(" указатели + %d: %10 u %10u \n", index, pti + index, ptf + index);
}
Вот результат:
указатели + 0 56014 56026
указатели + 1 56016 56030
указатели + 2 56018 56034
указатели + 3 56020 56038
Первая напечатанная строка содержит начальные адреса двух массивов, а следующая строка - результат прибавления единицы к адресу и т. д. Почему так получается?
56014 + 1 = 56016? 56026 + 1 = 56030?
Не знаете, что сказать? В нашей системе единицей адресации является байт, но тип intиспользует два байта, а тип float- четыре. Что произойдет, если вы скажете: "прибавить единицу к указателю?" Компилятор языка Си добавит единицу памяти . Для массивов это означает, что мы перейдем к адресу следующего элемента , а не следующего байта. Вот почему мы должны специально оговаривать тип объекта, на который ссылается указатель; одного адреса здесь недостаточно, так как машина должна знать, сколько байтов потребуется для запоминания объекта. (Это справедливо также для указателей на скалярные переменные; иными словами, при помощи операции *ptнельзя получить значение.)

РИС. 12.1. Увеличение указателя массива.
Благодаря тому что компилятор языка Си умеет это делать, мы имеем следующие равенства:
dates + 2 == &dates[2] /* один и тот же адрес */
*(dates + 2) == dates[2] /* одно и то же значение */
Эти соотношения суммируют тесную связь между массивами и указателями. Они показывают, что можно использовать указатель для определения отдельного элемента массива, а также для получения его значения. По существу мы имеем два различных обозначения для одного и того же. Действительно, компилятор превращает обозначение массива в указатели, поэтому метод указателей более предпочтителен.
Между прочим, постарайтесь различать выражения *(dates + 2), и *dates + 2. Операция ( *) имеет более высокий приоритет, чeм +, поэтому последнее выражение означает
(*dates) + 2:
*(dates + 2) /* значение 3-го элемента массива dates */
Читать дальше