Главная » Просмотр файлов » Керниган и Ритчи - Язык программирования Си

Керниган и Ритчи - Язык программирования Си (793773), страница 23

Файл №793773 Керниган и Ритчи - Язык программирования Си (Керниган и Ритчи - Язык программирования Си) 23 страницаКерниган и Ритчи - Язык программирования Си (793773) страница 232019-04-24СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 23)

Если же функцияпомечена словом static, то ее имя становится невидимым вне файла, в котором она определена.Объявление static можно использовать и для внутренних переменных. Как и автоматические переменные,внутренние статические переменные локальны в функциях, но в отличие от автоматических они не возникаюттолько на период работы функции, а существуют постоянно. Это значит, что внутренние статическиепеременные обеспечивают постоянное сохранение данных внутри функции.Упражнение 4.11. Модифицируйте функцию getop так, чтобы отпала необходимость в функции ungetch.Подсказка: используйте внутреннюю статическую переменную.4.7. Регистровые переменныеОбъявление register сообщает компилятору, что данная переменная будет интенсивно использоваться.Идея состоит в том, чтобы переменные, объявленные register, разместить на регистрах машины,благодаря чему программа, возможно, станет более короткой и быстрой.

Однако компилятор имеет правопроигнорировать это указание.Объявление register выглядит следующим образом:register int x;register char с;и т. д. Объявление register может применяться только к автоматическим переменным и к формальнымпараметрам функции. Для последних это выглядит так:f( register unsigned m, register long n){register int i;…}На практике существуют ограничения на регистровые переменные, что связано с возможностями аппаратуры.Располагаться в регистрах может лишь небольшое число переменных каждой функции, причем толькоопределенных типов.

Избыточные объявления register ни на что не влияют, так как игнорируются вотношении переменных, которым не хватило регистров или которые нельзй разместить на регистре. Крометого, применительно к регистровой переменной независимо от того, выделен на самом деле для нее регистрили нет, не определено понятие адреса (см. главу 5).

Конкретные ограничения на количество и типырегистровых переменных зависят от машины.4.8. Блочная структураПоскольку функции в Си нельзя определять внутри других функций, он не является языком, допускающимблочную структуру программы в том смысле, как это допускается в Паскале и подобных ему языках. Нопеременные внутри функций можно определять в блочно-структурной манере. Объявления переменных(вместе с инициализацией) разрешено помещать не только в начале функции, но и после любой левойфигурной скобки, открывающей составную инструкцию. Переменная, описанная таким способом, "затеняет"переменные с тем же именем, расположенные в объемлющих блоках, и существует вплоть досоответствующей правой фигурной скобки. Например, вif (n > 0) {int i; /* описание новой переменной i */for (i = 0; i < n; i++)…}областью видимости переменной i является ветвь if, выполняемая при n>0; и эта переменная никакогоотношения к любым i, расположенным вне данного блока, не имеет.

Автоматические переменные,объявленные и инициализируемые в блоке, инициализируются каждый раз при входе в блок. Переменныеstatic инициализируются только один раз при первом входе в блок.Автоматические переменные и формальные параметры также "затеняют" внешние переменные и функции стеми же именами. Например, вint x;int у;f(double x){double у;…}х внутри функции f рассматривается как параметр типа double, в то время как вне f это внешняяпеременная типа int. То же самое можно сказать и о переменной y.С точки зрения стиля программирования, лучше не пользоваться одними и теми же именами для разныхпеременных, поскольку слишком велика возможность путаницы и появления ошибок.4.9.

ИнициализацияМы уже много раз упоминали об инициализации, но всегда лишь по случаю, в ходе обсуждения другихвопросов. В этом параграфе мы суммируем все правила, определяющие инициализацию памяти различныхклассов.При отсутствии явной инициализации для внешних и статических переменных гарантируется их обнуление;автоматические и регистровые переменные имеют неопределенные начальные значения ("мусор").Скалярные переменные можно инициализировать в их определениях, помещая после имени знак = исоответствующее выражение:int x = 1;char squote = '\'';long day = 1000L * 60L * 60L * 24L; /* день в миллисекундах */Для внешних и статических переменных инициализирующие выражения должны быть константными, приэтом инициализация осуществляется только один раз до начала выполнения программы.

Инициализацияавтоматических и регистровых переменных выполняется каждый раз при входе в функцию или блок. Длятаких переменных инициализирующее выражение — не обязательно константное. Это может быть любоевыражение, использующее ранее определенные значения, включая даже и вызовы функций. Например, впрограмме бинарного поиска, описанной в параграфе 3.3, инициализацию можно записать так:int binsearch(int x, int v[], int n){int low = 0;int high = n - 1;int mid;а не так:int low, high, mid;low = 0;high = n - 1;В сущности, инициализация автоматической переменной — это более короткая запись инструкцииприсваивания.

Какая запись предпочтительнее — в большой степени дело вкуса. До сих пор мы пользовалисьглавным образом явными присваиваниями, поскольку инициализация в объявлениях менее заметна идальше отстоит от места использования переменной.Массив можно инициализировать в его определении с помощью заключенного в фигурные скобки спискаинициализаторов, разделенных запятыми. Например, чтобы инициализировать массив days, элементыкоторого суть количества дней в каждом месяце, можно написать:int days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};Если размер массива не указан, то длину массива компилятор вычисляет по числу заданныхинициализаторов; в нашем случае их количество равно 12.Если количество инициализаторов меньше числа, указанного в определении длины массива, то для внешних,статических и автоматических переменных оставшиеся элементы будут нулевыми.

Задание слишкомбольшого числа инициализаторов считается ошибкой. В языке нет возможности ни задавать повторенияинициализатора, ни инициализовать средние элементы массива без задания всех предшествующих значений.Инициализация символьных массивов — особый случай: вместо конструкции с фигурными скобками изапятыми можно использовать строку символов. Например, возможна такая запись:char pattern[] = "ould";представляющая собой более короткий эквивалент записиchar pattern[] = {'о', 'u', 'l', 'd', '\0'};В данном случае размер массива равен пяти (четыре обычных символа и завершающий символ '\0').4.10.

РекурсияВ Си допускается рекурсивное обращение к функциям, т.е. функция может обращаться сама к себе, прямо иликосвенно. Рассмотрим печать числа в виде строки символов. Как мы упоминали ранее, цифры генерируются вобратном порядке — младшие цифры получаются раньше старших, а печататься они должны в правильнойпоследовательности.Проблему можно решить двумя способами. Первый — запомнить цифры в некотором массиве в том порядке,как они получались, а затем напечатать их в обратном порядке; так это и было сделано в функции itoa,рассмотренной в параграфе 3.6.

Второй способ — воспользоваться рекурсией, при которой printd сначалавызывает себя, чтобы напечатать все старшие цифры, и затем печатает последнюю младшую цифру. Этапрограмма, как и предыдущий ее вариант, при использовании самого большого по модулю отрицательногочисла работает неправильно.#include <stdio.h>/* printd: печатает n как целое десятичное число */void printd(int n){if (n < 0) {putchar('-');n = -n;}if (n / 10)printd(n / 10);putchar(n % 10 + '0');}Когда функция рекурсивно обращается сама к себе, каждое следующее обращение сопровождаетсяполучением ею нового полного набора автоматических переменных, независимых от предыдущих наборов.Так, в обращении printd(123) при первом вызове аргумент n = 123,при втором — printd получаетаргумент 12, при третьем вызове — значение 1.

Функция рrintd на третьем уровне вызова печатает 1 ивозвращается на второй уровень, после чего печатает цифру 2 и возвращается на первый уровень. Здесь онапечатает 3 и заканчивает работу.Следующий хороший пример рекурсии — это быстрая сортировка, предложенная Ч. А. Р. Хоаром в 1962 г. Длязаданного массива выбирается один элемент, который разбивает остальные элементы на два подмножества— те, что меньше, и те, что не меньше него.

Та же процедура рекурсивно применяется и к двум полученнымподмножествам. Если в подмножестве менее двух элементов, то сортировать нечего, и рекурсия завершается.Наша версия быстрой сортировки, разумеется, не самая быстрая среди всех возможных, но зато одна изсамых простых.

В качестве делящего элемента мы используем серединный элемент./* qsort: сортирует v[left]...v[right] по возрастанию */void qsort(int v[], int left, int right){int i, last;void swap(int v[], int i, int j);if (left >= right) /* ничего не делается, если */return; /* в массиве менее двух элементов */swap(v, left, (left + right)/2); /* делящий элемент */last = left; /* переносится в v[0] */for(i = left+1; i <= right; i++) /* деление на части */if (v[i] < v[left])swap(v, ++last, i);swap(v, left, last); /* перезапоминаем делящий элемент */qsort(v, left, last-1);qsort(v, last+1, right);}В нашей программе операция перестановки оформлена в виде отдельной функции (swap), посколькувстречается в qsort трижды./* swap: поменять местами v[i] и v[j] */void swap(int v[], int i, int j){int temp;temp = v[i];v[i] = v[j];v[j] = temp;}Стандартная библиотека имеет функцию qsort, позволяющую сортировать объекты любого типа.Рекурсивная программа не обеспечивает ни экономии памяти, поскольку требуется где-то поддерживать стекзначений, подлежащих обработке, ни быстродействия; но по сравнению со своим нерекурсивнымэквивалентом она часто короче, а часто намного легче для написания и понимания.

Характеристики

Тип файла
PDF-файл
Размер
2,25 Mb
Тип материала
Высшее учебное заведение

Список файлов книги

Свежие статьи
Популярно сейчас
Почему делать на заказ в разы дороже, чем купить готовую учебную работу на СтудИзбе? Наши учебные работы продаются каждый год, тогда как большинство заказов выполняются с нуля. Найдите подходящий учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
7021
Авторов
на СтудИзбе
260
Средний доход
с одного платного файла
Обучение Подробнее