Даже из этого сравнительно простого
Даже из этого сравнительно простого примера видно, что заголовочные файлы и программы, структурированные подобным образом, получаются довольно запутанными и сопровождать их достаточно сложно. Возможно, проще использовать отдельный заголовочный файл для каждого компилятора или среды. При этом придется сопровождать множество отдельных файлов, но каждый из них будет предназначен только для использования в конкретной конфигурации, что уменьшит вероятность появления ошибок вроде включения функции st rdup в среду, строго поддерживающую стандарт ANSI С.
Заголовочные файлы также иногда "засоряют" пространство имен, определяя функции с именами, уже использующимися в программе. Например, наша функция оповещения об ошибках wep rintf изначально называлась wp rintf, однако мы выяснили, что в некоторых средах функция с таким именем определена в stdio. h (можно сказать, что сделано это в преддверии нового стандарта С). Для того чтобы скомпилировать программу в этих средах и защитить себя в будущем, нам пришлось изменить название своей функции. Если бы проблема состояла в некорректном компиляторе, а не в ожидаемом изменении спецификации, как в нашем случае, то ее можно было бы решить, переопределяя имя при подключении заголовочного файла:
Этот фрагмент изменяет все появления wprintf в заголовочном файле на stdio_wp rintf, так что теперь они не повлияют на нашу версию. Теперь мы можем использовать нашу wprintf, не изменив ее имени, правда, при этом неизбежно появится некая путаница, а также риск, что подключенная библиотека будет вызывать нашу wprintf, подра-
зумевая обращение к своей версии. Для одной функции проблемы, может, и невелики, но уже для нескольких лучше придумать более радикальное решение. Всегда комментируйте назначение конструкции; без крайней необходимости не ухудшайте ее добавлением условной компиляции. Если в некоторых средах определена wprintf, то стоит считать, что она определена во всех; тогда единственный разумный выход — переименовать ее, избавившись при этом от выражения tfifdef. Нередко проще не превозмогать трудность, а подстраиваться под нее; да это и безопаснее, вот почему мы решили переименовать свою функцию в weprintf.
Даже если вы следуете всем правилам и неясностей со средой не возникает, все равно вполне возможно появление ошибок. Так, можно ошибиться, предположив, что какая-нибудь ваша излюбленная возможность одинакова во всех системах. К примеру, ANSI С определяет шесть сигналов, которые можно поймать с помощью signal, в стандарте POSIX их определено 19, а большинство"систем Unix поддерживает 32 и более. Если вы хотите использовать сигнал, отличный от описанного в ANSI С, вам придется выбирать между функциональностью и переносимостью, так что сами решайте *ITO для вас важнее.
Существует болыпсте количество других стандартов, не являющихся частью определения языка: среди них можно назвать интерфейсы операционных систем и сетей, графические интерфейсы и тому подобные вещи. Некоторые стандарты распространяются на несколько систем — например POSIX; другие определены исключительно для одной системы, например различные API Microsoft Windows. Здесь можно еще раз повторить наши главные советы: ваша программа станет более переносимой, если вы выберете самые распространенные и устоявшиеся стандарты и будете пользоваться самыми важными и общепринятыми их свойствами.
<>
Содержание раздела