- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Язык Си - руководство для начинающих - M. УЭИТ
Шрифт:
Интервал:
Закладка:
Автоматические и регистровые массивы инициализировать нельзя.
Прежде чем попытаться инициализировать массив, давайте посмотрим, чтo там находится, если мы в него ничего не записали.
/* проверка содержимого массива */
main( ) {
int fuzzy[2]; /*автоматический массив */
static int wuzzy[2]; /* статический массив */
printf("%d %dn", fuzzy[1], wuzzy[1];
}
Программа напечатает
525 0
Полученный результат иллюстрирует следующее правило:
Если ничего не засылать в массив перед началом работы с ним, то внешние и статические массивы инициализируются нулем, а автоматические и статические массивы содержат какой-то "мусор", оставшийся в этой частя памяти.
Прекрасно! Теперь мы знаем, что нужно предпринять для обнуления статического или внешнего массива - просто ничего не делать. Но как быть, если нам нужны некоторые значения, отличные от нуля, например количество дней в каждом месяце. В этом случае мы можем делать так:
/* дни месяца */
int days[12]=[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
main( )
{
int index;
extern int days[ ]; /* необязательное описание */
for(index = 0; index < 12; index++)
printf(" Месяц %d имеет %d дней.n", index + 1, days[index]);
}
Результат:
Месяц 1 имеет 31 дней. Месяц 2 имеет 28 дней. Месяц 3 имеет 31 дней.
Месяц 4 имеет 30 дней. Месяц 5 имеет 31 дней. Месяц 6 имеет 30 дней.
Месяц 7 имеет 31 дней. Месяц 8 имеет 31 дней. Месяц 9 имеет 30 дней.
Месяц 10 имеет 31 дней. Месяц 11 имеет 30 дней. Месяц 12 имеет 31 дней.
Программа не совсем корректна, поскольку она выдает неправильный результат для второго месяца каждого четвертого года.
Определив массив days[ ] вне тела функции, мы тем самым сделали его внешним. Мы инициировали его списком, заключенным в скобки, используя при этом запятые для разделения элементов списка.
Количество элементов в списке должно соответствовать размеру массива. А что будет, если мы ошиблись в подсчете? Попробуйте переписать последний пример, используя список, который короче, чем нужно (на два элемента):
/* дни месяца */
int days[12]=[31, 28, 31, 30, 31, 30, 31, 31, 30, 31];
main( )
{
int index;
extern int days[ ]; /* необязательное описание */
for(index = 0; index < 12; index++)
printf(" Месяц %d имеет %d дней.n", index + 1, days[index]);
}
В этом случае результат оказывается иным:
Месяц 1 имеет 31 дней.
Месяц 2 имеет 28 дней.
Месяц 3 имеет 31 дней.
Месяц 4 имеет 30 дней.
Месяц 5 имеет 31 дней.
Месяц 6 имеет 30 дней.
Месяц 7 имеет 31 дней.
Месяц 8 имеет 31 дней.
Месяц 9 имеет 30 дней.
Месяц 10 имеет 31 дней.
Месяц 11 имеет 0 дней.
Месяц 12 имеет 0 дней.
Можно видеть, что у компилятора не возникло никаких проблем: просто когда он исчерпал весь список с исходными данными, то стал присваивать всем остальным элементам массива нулевые значения.
Однако в случае излишне большого списка компилятор будет уже не столь "великодушен" к вам, поскольку посчитает выявленную избыточность ошибкой. Поэтому нет никакой необходимости заранее подвергать себя "насмешкам" компилятора. Надо просто выделить массив, размер которого будет достаточен для размещения списка:
/* дни месяца */
int days[ ]=[31, 28, 31, 30, 31, 30, 31, 31, 30, 31];
main( )
{
int index;
extern int days[ ]; /* необязательное описание */
for(index = 0; index < sizeof days/(sizeof (int)); index++)
printf(" Месяц %d имеет %d дней.n", index + 1, days [index]);
}
К этой программе следует сделать два существенных замечания:
Первое: если вы используете пустые скобки для инициализации массива, то компилятор сам определит количество элементов в списке и выделит для него массив нужного размера.
Второе: оно касается добавления, сделанного п управляющем операторе for. He полагаясь (вполне обоснованно) на свои вычислительные способности, мы возложили задачу подсчета размера массива на компилятор. Оператор sizeof определяет размер в байтах объекта или типа, следующего за ним. (Мы. уже упоминали об этом в гл. 3.) В нашей вычислительной системе размер каждого элемента типа int равен двум байтам, поэтому для получения количества элементов массива мы делим общее число байтов, занимаемое массивом, на 2. Однако в других системах элемент типа int может иметь иной размер. Поэтому в общем случае выполняется деление на значение переменной sizeof (для элемента типа int). Ниже приведены результаты работы нашей программы:
Месяц 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 нельзя получить значение.)

