• Операторы проверки предоставляют способ сделать утверждения о предполагаемом состоянии программы. Они являются полезным инструментом для проектирования и отладки и обычно должны оставаться в коде изделия. Однако, будьте внимательны, чтобы не перепутать операторы проверки с проверками возможных ошибок времени исполнения.
• Функции mem
являются аналогичными более известным функциям str
. Самой большой их ценностью является то. что они могут работать с двоичными данными; нулевые байты не отличаются от других байтов. Больше известна memcpy()
против memmove()
, обрабатывающей перекрывающиеся копии.
• Временные файлы полезны во многих приложениях. Функции API tmpfile()
и mkstemp()
являются предпочтительными способами создания временных файлов, в то же время позволяя избежать состояния гонки и связанных с ней проблем безопасности. Многие программы для указания местоположения своих временных файлов используют переменную окружения TMPDIR
, а если она не определена, приемлемое значение по умолчанию (обычно /tmp
). Это хорошее соглашение, которое следует принять на вооружение в своих программах.
• Функция abort()
посылает вызывающему процессу сигнал SIGABRT
. Результатом является завершение процесса и создание дампа ядра, предположительно для отладки.
• setjmp()
и longjmp()
обеспечивают нелокальный переход. Это мощная возможность, которая должна использоваться с осторожностью. sigsetjmp()
и siglongjmp()
сохраняют и восстанавливают маску сигналов процесса, когда программа осуществляет нелокальный переход. Проблемы с нелокальными переходами иногда перевешивают их преимущества, соответственно используйте эти процедуры лишь когда нет лучшего способа структурировать ваше приложение.
• Случайные числа полезны для множества приложений. Большинство программ используют псевдослучайные числа — последовательности номеров, которые кажутся случайными, но которые могут быть воспроизведены с помощью одного и того же начального значения. rand()
и srand()
являются первоначальными функциями API, стандартизованными языком С. На многих системах rand()
использует низкокачественный алгоритм, random()
и srandom()
используют лучший алгоритм, включены в стандарт POSIX и являются предпочтительными по сравнению с rand()
и srand()
. Используйте специальные файлы /dev/random
и /dev/urandom
, если (а) они доступны и (б) если вам нужны случайные числа высокого качества.
• Три функции API предоставляют все более мощные возможности для развертывания метасимволов (подстановки символов).
• fnmatch()
является простейшей, возвращающей true/false, если данная строка соответствует или не соответствует шаблону символов подстановки оболочки.
• glob()
просматривает файловую систему, возвращая список путей, которые соответствуют данному шаблону. Когда требуются стандартные возможности glob()
, следует использовать эту функцию. Хотя GLIBC версия glob()
имеет некоторые расширения, переносимые программы, которым нужны дополнительные возможности, должны вместо этого использовать wordexp()
. (Программы, которые будут работать лишь на системах GNU/Linux, не должны стесняться использовать полную мощь GLIBC glob()
.)
• wordexp()
не только делает то, что делает glob()
, но также выполняет полное развертывание слов в стиле оболочки, включая развертывание тильды, развертывание переменных оболочки и подстановку команд.
• Функции regcomp()
и regexec()
обеспечивают доступ к базовым и расширенным регулярным выражениям POSIX. Используя одну из этих функций, можно заставить свою программу вести себя идентично со стандартными утилитами, значительно упрощая использование программы пользователями, знакомыми с GNU/Linux и Unix.
Упражнения
1. Используйте read()
и memcmp()
для написания простой версии программы cmp
, которая сравнивает два файла. Вашей версии не нужно поддерживать какие-нибудь опции.
2. Используйте макрос
и прямое сравнение каждого прочитанного символа для написания другой версии cmp
, которая сравнивает два файла. Сравните производительность этой версии с производительностью написанной в предыдущем упражнении.
3. (Средней трудности) Рассмотрите функции
и GLIBC getline()
. Полезна ли memcpy()
для их реализации? Набросайте с ее использованием возможную реализацию fgets()
.
4. (Трудное) Найдите исходный код GLIBC версии memcmp()
. Он должен быть на одном из CD-ROM с исходным кодом в вашем дистрибутиве GNU/Linux, или же вы можете найти его в сети. Исследуйте код и объясните его.
5. Проверьте свою память. Как tmpfile()
организует удаление файла, когда закрыт указатель файла?
6. Используя mkstemp()
и fdopen()
, а также другие необходимые функции или системные вызовы, напишите свою версию tmpfile()
. Протестируйте ее тоже.