Использование стандартных функций: и — КиберПедия 

Автоматическое растормаживание колес: Тормозные устройства колес предназначены для уменьше­ния длины пробега и улучшения маневрирования ВС при...

Своеобразие русской архитектуры: Основной материал – дерево – быстрота постройки, но недолговечность и необходимость деления...

Использование стандартных функций: и

2021-01-29 65
Использование стандартных функций: и 0.00 из 5.00 0 оценок
Заказать работу

 

Нелокальные переходы осуществляются с помощью функций и. Эти функции используются в двух разновидностях. Традиционные процедуры определены стандартом ISO С:

 

 

Тип определен через в. сохраняет текущее «окружение» в. обычно является глобальной или статической на уровне файла переменной, так что она может использоваться из вызванной функции. Это окружение включает любую информацию, необходимую для перехода на местоположение, из которого была вызвана. Содержание по своей природе машинно‑зависимо; таким образом, является непрозрачным типом: тем, что вы используете, не зная, что находится внутри него.

 возвращает 0, когда она вызывается для сохранения в текущего окружения. Ненулевое значение возвращается, когда с использованием окружения осуществляется нелокальный переход:

 

 осуществляет переход. Первым параметром является, который должен быть инициализирован с помощью. Второй является целым ненулевым значением, которое возвращает в первоначальное окружение. Это сделано так, что код, подобный только что показанному, может различить установку окружения и прибытие путем нелокального перехода.

Стандарт С утверждает, что даже если вызывается со вторым аргументом, равным 0, по‑прежнему возвращает ненулевое значение. В таком случае она возвращает 1.

Возможность передать целое значение и вернуться обратно из полезна; это позволяет коду уровня пользователя различать причину перехода. Например, использует эту возможность для обработки операторов и внутри циклов. (Язык awk осознанно сделан похожим на С в своем синтаксисе для циклов, с использованием,,, и.) Использование выглядит следующим образом (из в дистрибутиве 3.1.3):

 

Этот фрагмент кода представляет цикл. Строка 508 управляет вложенными циклами посредством стека сохраненных переменных. Строки 511–524 выполняют цикл (используя цикл С!). Строка 511 проверяет условие цикла. Если оно истинно, строка 513 выполняет на возвращаемое значение. Если оно равно 0 (строки 514–516), строка 515 выполняет тело оператора. Однако, когда возвращает или, оператор обрабатывает их соответствующим образом (строки 517–518 и 519–521 соответственно).

Оператор на уровне передает функции, a уровня передает. Снова из с некоторыми пропущенными не относящимися к делу подробностями:

 

Вы можете думать о как об установке метки, а о как выполнении с дополнительным преимуществом возможности сказать, откуда «пришел» код (по возвращаемому значению).

 

Обработка масок сигналов: и

 

По историческим причинам, которые, скорее всего, утомили бы вас до слез, стандарт С 1999 г. ничего не говорит о влиянии и на состояние сигналов процесса, а POSIX явно констатирует, что их влияние на маску сигналов процесса (см. раздел 10.6 «Сигналы POSIX») не определено.

Другими словами, если программа изменяет свою маску сигналов процесса между первым вызовом и вызовом, каково состояние маски сигналов процесса после? Та ли эта маска, когда была впервые вызвана? Или это текущая маска? POSIX явно утверждает, что «нет способа это узнать».

Чтобы сделать обработку маски сигналов процесса явной, POSIX ввел две дополнительные функции и один:

 

Главным отличием является аргумент функции. Если он не равен нулю, текущий набор заблокированных сигналов сохраняется в вместе с остальным окружением, которое сохраняется функцией. с, в которой содержала true, восстанавливает сохраненную маску сигналов процесса

 

ЗАМЕЧАНИЕ. POSIX также ясен в том, что если равен нулю (false), сохраняется ли маска сигналов процесса или восстанавливается, не определено, как в случае с /. Это, в свою очередь, предполагает, что если собираетесь использовать '', вы также можете не беспокоиться: все дело в том, чтобы иметь контроль над сохранением и восстановлением маски сигналов процесса!

 

 

Важные предостережения

 

Есть несколько технических предостережений, о которых нужно знать.

Во‑первых, поскольку сохранение и восстановление среды может быть беспорядочной машинно‑зависимой задачей, и могут быть макросами

Во‑вторых, стандарт С ограничивает использование следующими ситуациями.

• В качестве единственного контролирующего выражения в операторе цикла или условном операторе (,).

• В качестве одного операнда выражения сравнения (, и т.д.), с целой константой в качестве другого операнда. Выражение сравнения может быть единственный контролирующим выражением цикла или условного оператора.

• В качестве операнда унарного оператора '', причем результирующее выражение является единственным контролирующим выражением цикла или условного оператора.

• В качестве всего выражения оператора‑выражения, возможно, приведенного к типу. Например:

 

В‑третьих, если вы хотите изменить локальную переменную в функции, которая вызывает, после вызова и хотите, чтобы эта переменная сохранила свое последнее присвоенное после значение, нужно объявить эту переменную как. В противном случае все локальные переменные, не являющиеся и изменившиеся после того, как была первоначально вызвана, имеют неопределенные значения. (Обратите внимание, что сама переменная не должна объявляться как.) Например:

 

 

В этом примере сохранение своего значения ко второму вызову гарантируется j (строка 21). Значение (строка 20) в соответствии со стандартом С 1999 г. не определено. Это может быть 6, может быть 5, а может даже какое‑нибудь другое значение!

В‑четвертых, как описано в разделе 12.5.2 «Обработка масок сигналов: и», стандарт С 1999 г. не делает никаких утверждений о влиянии, если оно есть, и на состояние сигналов программы. Если это важно, вам придется вместо них использовать и.

В‑пятых, эти процедуры содержат поразительные возможности для утечек памяти! Рассмотрим программу, в которой вызывает, а затем вызывает несколько вложенных функций, каждая из которых выделяет с помощью динамическую память. Если наиболее глубоко вложенная функция делает обратно в, указатели на динамическую память теряются. Взгляните на:

 

Эта программа устанавливает бесконечный цикл, используя и. Строка 20 использует для нахождения текущего начала кучи (см. раздел 3.2.3 «Системные вызовы: и»), а затем строка 22 вызывает. Строка 25 получает текущее начало кучи; это место каждый раз изменяется, поскольку повторно входит в код. Строки 27–28 вычисляют, сколько было выделено памяти, и выводят это количество. Вот что происходит при запуске:

ch12‑memleak

 

 

Память утекает из программы, как через решето. Она работает до тех пор, пока не будет прервана от клавиатуры или пока не закончится память (в этом случае образуется основательный дамп ядра).

Каждая из функций и выделяют память, a выполняет обратно в (строка 51). Когда это происходит, локальные указатели (строки 39 и 48) на выделенную память пропали! Такие утечки памяти может оказаться трудно отследить, поскольку часто выделяются небольшие размеры памяти, и как таковые, они могут оставаться незамеченными в течение ряда лет[128].

Этот код явно патологический, но он предназначен для иллюстрации нашей мысли: и могут вести к трудно обнаруживаемым утечкам памяти. Предположим, что правильно вызвал. Было бы далеко неочевидно, что память никогда не будет освобождена. В более крупной и более реалистичной программе, в которой мог быть вызван лишь посредством, найти такую утечку становится даже еще труднее.

Таким образом, при наличии и динамическая память должна управляться посредством глобальных переменных, а у вас должен быть код, который обнаруживает вход через (посредством проверки возвращаемого значения). Такой код должен затем освободить динамически выделенную память, которая больше не нужна.

В‑шестых, и не следует использовать из функций, зарегистрированных посредством (см. раздел 9.1.5.3 «Функции завершения»).

В‑седьмых, и могут оказаться дорогими операциями на машинах с множеством регистров.

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

 

 

Псевдослучайные числа

 

Многим приложениям нужны последовательности случайных чисел. Например, игровые программы, имитирующие бросание костей, раздачу карт или вращение барабанов игровой машины, нуждаются в возможности случайного выбора одного из возможных значений. (Подумайте о программе, содержащей большую коллекцию афоризмов; каждый раз при запуске она «случайно» выдает новое высказывание.) Многие криптографические алгоритмы также требуют наличия случайных чисел «высокого качества». В данном разделе описываются различные способы получения последовательностей случайных чисел.

 

ЗАМЕЧАНИЕ. Природа случайности, генерация случайных чисел и их «качество» являются обширными темами, выходящими за рамки данной книги. Мы предоставляем введение в доступные функции API, но это все, что мы можем сделать Другие источники с более подробной информацией см в разделе 12.9 «Рекомендуемая литература»

 

Компьютеры по своему строению являются детерминистическими. Одно и то же вычисление с одними и теми же входными данными всегда должно давать одни и те же результаты. Соответственно, они не годятся для генерации истинно случайных чисел, то есть последовательностей чисел, в которых каждое число в последовательности полностью независимо от числа (или чисел), идущих перед ним. Вместо этого разновидности чисел, обычно используемых на программном уровне, называются псевдослучайными числами. То есть в любой данной последовательности номера выглядят независимыми друг от друга, но сама последовательность в целом повторяющаяся. (Эта повторяемость может быть ценным качеством; она обеспечивает детерминизм для программы в целом.)

Многие методы предоставления последовательностей псевдослучайных чисел работают посредством осуществления каждый раз одного и того же вычисления с начальным значением (seed). Сохраненное начальное значение затем обновляется для использования в следующий раз. API предоставляет способ указания нового начального значения. Каждое начальное значение дает одну и ту же последовательность псевдослучайных чисел, хотя различные начальные числа дают (должны давать) различные последовательности.

 

Стандартный С: и

 

Стандартный С определяет две связанные функции для псевдослучайных чисел.

 

 

 каждый раз после вызова возвращает псевдослучайное число в диапазоне от 0 до (включительно, насколько мы можем судить по стандарту C99). Константа должна быть по крайней мере 32 767; она может быть больше.

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

Следующая программа,, использует для вывода граней игральных костей.

 

Эта программа использует простую ASCII‑графику для распечатывания подобия грани игральной кости. Вы вызываете ее с числом граней для вывода. Это вычисляется в строке 44 с помощью. (В общем, следует избегать в коде изделия, поскольку она не осуществляет проверку на ошибки или переполнение, также как не проверяет вводимые данные.)

Ключевой является строка 53, которая преобразует возвращаемое значение в число от нуля до пяти, используя оператор остатка,. Значение '' действует в качестве начального индекса массива для трех строк, составляющих каждую грань кости. Строки 55 и 56 выводят саму грань. При запуске появляется вывод наподобие этого:

ch12‑rand

 

 

Интерфейс восходит еще к V7 и PDP‑11. В частности, на многих системах результатом является лишь 16‑разрядное число, что значительно ограничивает диапазон чисел, которые могут быть возвращены. Более того, используемый им алгоритм по современным стандартам считается «слабым». (Версия GLIBC не имеет этих проблем, но переносимый код должен быть написан со знанием того, что не является лучшим API для использования.)

 использует для получения значения в определенном интервале простую методику: оператор. Эта методика использует младшие биты возвращенного значения (как при десятичном делении, когда остаток отделения на 10 или 100 использует одну или две младшие десятичные цифры). Оказывается, исторический генератор производил лучшие случайные значения в средних и старших битах по сравнению с младшими битами. Поэтому, если вы должны использовать, постарайтесь избежать младших битов. Справочная страница GNU/Linux rand (3) цитирует «Числовые рецепты на С»[129], которая рекомендует эту методику:

 

 

Функции POSIX: и

 

BSD 4.3 ввело random() и сопровождающие ее функции. Эти функции используют намного более подходящий генератор случайных чисел, который возвращает 31‑разрядное значение. Теперь они входят в расширение XSI, стандартизованное POSIX:

 

 

Первые две функции близко соответствуют и и могут использоваться сходным образом. Однако, вместо одного начального значения, которое дает последовательность псевдослучайных чисел, эти функции используют начальное значение вместе с массивом состояния: массивом байтов, который хранит сведения о состоянии для вычисления псевдослучайных чисел. Последние две функции дают возможность управлять массивом состояния.

 

Возвращает число в диапазоне от 0 до 231‑1. (Хотя справочная страница GNU/Linux random (3) говорит между 0 и, это верно лишь для систем GLIBC, где равен 231‑1. На других системах может быть меньше. POSIX явно называет диапазон от 0 до 231‑1.)

 

Устанавливает начальное число. Если никогда не вызывается, по умолчанию используется 1.

 

Инициализирует массив информацией для использования при генерации случайных чисел, является начальным значением, как для, а является числом байтов в массиве.

 должен равняться одному из значений 8, 32, 64, 128 или 256. Большие значения дают лучшие последовательности случайных чисел. Значения меньше 8 заставляют использовать простой генератор случайных чисел, сходный с. Значения больше 8, не равные одному из значений в списке, округляются до ближайшего подходящего значения.

 

Устанавливает внутреннее состояние в соответствии с массивом, который должен быть инициализирован посредством. Это позволяет переключаться по желанию между различными состояниями, предоставляя множество генераторов случайных чисел.

Если и никогда не вызывались, использует массив внутреннего состояния размером 128.

Массив непрозрачен; вы инициализируете его с помощью и передается функции посредством, но в другом отношении вам не нужно заглядывать в него. Если вы используете и. вызывать не нужно, поскольку начальное значение включено в информацию о состоянии. использует эти процедуры вместо. Используется также обычная методика, которая заключается в использовании в качестве начального значения генератора случайных чисел времени дня, добавленного к PID.

 

 

Включение PID в состав начального значения гарантирует, что вы получите различные результаты, даже если две программы будут запушены в течение одной и той же секунды.

Поскольку она создает последовательности случайных чисел лучшего качества, является более предпочтительной по сравнению с, и GNU/Linux и все современные системы Unix ее поддерживают.

 

Особые файлы и

 

Как, так и являются генераторами псевдослучайных чисел. Их вывод для одного и того же начального значения является воспроизводимой последовательностью чисел. Некоторым приложениям, подобным криптографическим, необходимо, чтобы их случайные числа были действительно (более) случайными. С этой целью ядро Linux, также как различные BSD и коммерческие Unix системы предусматривают специальные файлы устройств, которые предоставляют доступ к «энтропийному пулу» случайных битов, которые ядро собирает от физических устройств и других источников. Из справочной страницы random (4):

 

[Байты, прочитанные из этого файла, находятся] внутри предполагаемого числа шумовых битов в энтропийном пуле, должен подходить для использования в случаях, когда необходим высокий уровень случайности, таких, как одноразовая генерация ключа или блока памяти. Когда энтропийный пул пустой, чтение будет блокироваться до тех пор, пока не будет собран дополнительный шум окружения.

 

[Это устройство будет] возвращать столько байтов, сколько затребовано. В результате, если нет достаточной энтропии в энтропийном пуле, возвращаемые значения теоретически уязвимы для криптографической атаки алгоритма, использованного драйвером. Знание того, как это сделать, недоступно в современной не секретной литературе, но теоретически возможно существование подобной атаки. Если для вашего приложения это представляет проблему, вместо этого используйте.

Для большинства приложений чтения из должно быть вполне достаточно. Если вы собираетесь написать криптографические алгоритмы высокого качества, следует сначала почитать о криптографии и случайности; не полагайтесь здесь на поверхностное представление! Вот еще одна наша программа для бросания костей, использующая:

 

 

Строки 35–47 предоставляют интерфейс вызова функции для, читая каждый раз данные. Издержками является один дескриптор файла, который остается открытым в течение жизни программы.

 

 

Расширения метасимволов

 

Три набора функции возрастающей сложности предусматривают возможность сопоставления с шаблонами групповых символов оболочки. Многим программам нужны такие библиотечные функции. Одним примером является: ''. Другим примером является опция во многих программах, которая принимает шаблон файлов с групповыми символами для исключения из того или иного действия. В данном разделе по очереди рассматривается каждый набор функций.

 


Поделиться с друзьями:

Археология об основании Рима: Новые раскопки проясняют и такой острый дискуссионный вопрос, как дата самого возникновения Рима...

Индивидуальные и групповые автопоилки: для животных. Схемы и конструкции...

Общие условия выбора системы дренажа: Система дренажа выбирается в зависимости от характера защищаемого...

Состав сооружений: решетки и песколовки: Решетки – это первое устройство в схеме очистных сооружений. Они представляют...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.01 с.