Стандартная библиотека языка Си

Стандартная библиотека
языка программирования С

Стандартной библиотекой языка Си (также известная как libc, crt) называется часть стандарта ANSI C, посвященная заголовочным файлам и библиотечным подпрограммам. Является описанием реализации общих операций, таких как обработка ввода-вывода и строк в языке программирования Си. Стандартная библиотека языка Си — это описание программного интерфейса, а не настоящая библиотека, пригодная для использования в процессе компиляции.

Структура

Имя и характеристики каждой функции указываются в файле, именуемом заголовочным файлом, но текущая реализация функций описана отдельно в библиотечном файле. Наименование и возможности заголовочных файлов становятся общими, но организация библиотек по-прежнему остается разнотипной. Стандартная библиотека обычно поставляется вместе с компилятором. Так как компиляторы языка Си часто обеспечивают расширенную функциональность, не определенную стандартом ANSI C, стандартная библиотека одного компилятора несовместима со стандартными библиотеками других компиляторов.

Мнения о структуре

Большая часть стандартной библиотеки языка Си производит впечатление удачно спроектированной. Некоторые отдельные части, дававшие преимущество в прошлом, могут провоцировать ошибки. Функции строкового ввода gets() (и применение scanf() для считывания вводимых строк) являются источником множества переполнений буфера, поэтому большинство руководств по программированию советуют избегать подобных приемов. Функция strcpy() также весьма печально знаменита. Ещё одной неоднозначной функцией является strtok() — функция, разработанная как простейший лексический анализатор, но имеющая множество «подводных камней» и потому весьма трудная в использовании.

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

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

История

Язык программирования Си до стандартизации не обеспечивал встроенной функциональности, как, например, операции ввода-вывода (в отличие от таких традиционных языков, как Кобол и Фортран). Позже, в сообществе программистов, работавших с языком Си, зародились идеи, которые реализовались в то, что мы сейчас называем Стандартной библиотекой языка Си, для поддержки этой функциональности. Большинство этих идей в итоге объединились в определении стандарта языка программирования Си.

И Unix, и Си были созданы в AT&T’s Bell Laboratories в конце 1960-х — начале 1970-х. В 1970-е язык программирования Си начал пользоваться невероятной популярностью. Множество университетов и организаций начали создание собственных вариантов языка, более подходящих для собственных нужд. С началом 1980-х проблемы совместимости между различными реализациями языка Си стали слишком очевидными. В 1983 году Американский национальный институт стандартов (ANSI) сформировал комитет для принятия стандарта языка Си, известный как «ANSI Си». Эта работа вылилась в создание так называемого стандарта C89 в 1989. Часть итогового стандарта была набором библиотек, названная Стандартная библиотека ANSI Си.

Последующие версии стандарта языка Си добавляли некоторые новые и наиболее полезные заголовочные файлы в библиотеку. Поддержка этих новых расширений зависела от реализации.

Заголовочные файлы <iso646.h>, <wchar.h> и <wctype.h> были добавлены в Приложении 1 (сокращенно NA1) — дополнении к Стандарту языка Си, ратифицированному в 1995.

Заголовочные файлы <complex.h>, <fenv.h>, <inttypes.h>, <stdbool.h>, <stdint.h> и <tgmath.h> были добавлены в C99, версии Стандарта языка Си, опубликованном в 1999.

Стандарт ANSI

Стандартная библиотека ANSI Си состоит из 24 заголовочных файлов, каждый из которых можно подключать к программному проекту при помощи одной директивы. Каждый заголовочный файл содержит объявления одной или более функций, определения типов данных и макросы. Содержание этих заголовочных файлов перечисляется ниже.

В сравнении с некоторыми другими языками (например Java) стандартная библиотека крайне мала. Библиотека обеспечивает поддержку основного набора математических функций, обработку строк, конвертацию типов, файловый и консольный ввод-вывод. Она не содержит стандартный набор «контейнерных типов» как стандартная библиотека шаблонов языка C++, компоненты для работы с графическим пользовательским интерфейсом (GUI), сетью и прочей разнообразной функциональности, которую Java поддерживает по стандарту. Главным преимуществом маленькой стандартной библиотеки является упрощение работы с окружением ANSI Си по сравнению с другими языками, а следовательно и упрощение портирования программ на языке Си на новые платформы.

Множество прочих библиотек было разработано для поддержки схожей функциональности, обеспечиваемой другими языками в их стандартных библиотеках. Например, в проекте разработки окружения рабочего стола GNOME был разработан набор графических инструментов GTK+ и GLib — библиотека контейнерных структур данных, как впрочем и множество других известных примеров. Разнообразие доступных библиотек означает, что некоторые инструменты верхнего уровня, со временем подтвердили свою полезность. Значительным минусом является то, что они часто не слишком успешно взаимодействуют друг с другом, поэтому программистам зачастую привычнее работать с различными наборами библиотек, а их наборы могут быть доступны на различных специфических платформах.

Библиотечные заголовочные файлы ANSI Си c дополнениями C99 и C11

<assert.h> Содержит макрос утверждений, используемый для обнаружения логических и некоторых других типов ошибок в отлаживаемой версии программы.
<complex.h> Набор функций для работы с комплексными числами. (Появилось в C99)
<ctype.h> Содержит функции, используемые для классификации символов по их типам или для конвертации между верхним и нижним регистрами независимо от используемой кодировки (обычно ASCII или одно из её расширений, хотя есть и реализации, использующие EBCDIC).
<errno.h> Для проверки кодов ошибок, возвращаемых библиотечными функциями.
<fenv.h> Для управления средой, использующей числа с плавающей точкой. (Появилось в C99)
<float.h> Содержит заранее определенные константы, описывающие специфику реализации свойств библиотеки для работы с числами с плавающей точкой, как, например, минимальная разница между двумя различными числами с плавающей точкой (_EPSILON), максимальное число цифр точности (_DIG) и область допустимых чисел (_MIN, _MAX).
<inttypes.h> Для точной конвертации целых типов. (Появилось в C99)
<iso646.h> Для программирования в кодировке ISO 646. (Появилось в NA1)
<limits.h> Содержит заранее заданные константы, определяющие специфику реализации свойств целых типов, как, например, область допустимых значений (_MIN, _MAX).
<locale.h> Для setlocale() и связанных констант. Используется для выбора соответствующего языка.
<math.h> Для вычисления основных математических функций
<setjmp.h> Объявляет макросы setjmp и longjmp, используемые для нелокальных переходов
<signal.h> Для управления обработкой сигналов
<stdarg.h> Для доступа к различному числу аргументов, переданных функциям.
<stdbool.h> Для булевых типов данных. (Появилось в C99)
<stdint.h> Для определения различных типов целых чисел. (Появилось в C99)
<stddef.h> Для определения нескольких стандартных типов и макросов.
<stdio.h> Реализует основные возможности ввода и вывода в языке Си. Этот файл содержит весьма важную функцию printf.
<stdlib.h> Для выполнения множества операций, включая конвертацию, генерацию псевдослучайных чисел, выделение памяти, контроль процессов, окружения, сигналов, поиска и сортировки.
<string.h> Для работы с различными видами строк.
<tgmath.h> Для типовых математических функций. (Появилось в C99)
<threads.h> Заголовочный файл <threads.h> наряду с <stdatomic.h> предоставляет поддержку для параллельного программирования. (Появилась в C11)
<time.h> Для конвертации между различными форматами времени и даты.
<wchar.h> Для обработки «широких» потоков и нескольких видов строк при помощи «широких» символов (поддержка набора языков). (Появилось в NA1)
<wctype.h> Для классификации «широких» символов. (Появилось в NA1)

Стандартная библиотека Си в других языках

Некоторые языки обеспечивают функциональность стандартной библиотеки Си при помощи своих собственных библиотек. Библиотека может быть адаптирована для структур языка, но семантика операций остается схожей. Язык программирования C++, например, содержит функциональность стандартной библиотеки ANSI Си в пространстве имен std (например, std::printf, std::atoi, std::feof и т. д.), в заголовочных файлах со схожими именами как в Си («cstdio», «cmath», «cstdlib» и т. д.). К другим языкам, в которых применяются схожие подходы относятся, например, D и Python. В последнем, к примеру, встроенный объект file определен как «реализованный при помощи пакета stdio языка Си»[1], так что доступные операции (открытие, чтение, запись и т. д.), как ожидается, должны иметь поведение как у соответствующих функций языка Си.

Общая поддержка библиотек

Пока не стандартизировано, но программы на языке Си могут зависеть от библиотек подпрограмм, которые содержат код, используемый компилятором во время работы. Код, инициализирующий процесс для операционной системы, например, перед вызовом main(), реализован в библиотеке времени исполнения языка Си (C Run-Time Library, CRT) для данной версии компилятора. Код библиотеки CRT может помочь с реализацией других особенностей языка, как например, обработка неперехваченных исключений или реализация работы с числами с плавающей точкой.

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

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

Встроенные функции компилятора

Некоторые компиляторы (например, GCC[1]) поддерживают внутренние версии множества функций Стандартной библиотеки языка Си; то есть, реализации функций записываются в компилируемый объектный модуль, а программа вызывает внутренние версии вместо функций общей библиотеки Си. Это уменьшает накладные расходы при вызове функции, особенно если вызов функции заменяется встроенными вариантами, и разрешается использование других форм оптимизации (если компилятор поддерживает управление характеристиками внутренних вариантов), но может приводить к проблемами при отладке (например, внутренние версии не могут быть заменены инструментальными версиями для проверки).

Стандартная библиотека POSIX

POSIXSUS) определяют некоторое количество подпрограмм, которые могут быть доступны помимо определенных в стандартной библиотеке языка Си; они часто реализуют функциональность, аналогичную стандартной библиотеке, с различной степенью подобия. Например, glibc реализует такие функции, как fork, в libc.so, но перед вызовом библиотеки потоков объединяются в glibc, хотя это заявлено как отдельная библиотека с собственным флагом линковщика. Зачастую такая POSIX-совместимая функциональность рассматривается как часть библиотеки; соответствующая библиотека Си, таким образом, может быть идентифицирована как ANSI или ISO библиотека языка Си.

Реализации

Существует множество реализаций, поставляемых как с различными операционными системами, так и с компиляторами языка Си. На BSD системах, к примеру, системная библиотека встроена в операционную систему и поддерживается общим репозиторием исходников. На большинстве систем библиотека может быть найдена под именем «libc».

Хотя существует очень много реализаций, вот небольшой список самых популярных библиотек:

  • GNU C Library — самая распространенная реализация, используемая в Linux
  • Microsoft C Run-time Library
  • dietlibc — альтернативная небольшая реализация Стандартной библиотеки языка Си
  • uClibc — Стандартная библиотека языка Си для встраиваемых систем на базе Linux
  • Newlib — Стандартная библиотека языка Си для встраиваемых систем (MMU-less)[2]
  • klibc — применяется главным образом для загрузки Linux-систем.
  • eglibc — разновидность glibc для встраиваемых систем.
  • musl — реализация стандартной библиотеки языка Си для Linux, стремящаяся быть совместимой в первую очередь с современными стандартами, во вторую очередь с glibc.[3]

См. также

Ссылки

  1. Other built-in functions provided by GCC Архивная копия от 11 декабря 2008 на Wayback Machine, Руководство по GCC
  2. Re: Поддерживает ли Newlib процессоры mmu-less? Дата обращения: 3 октября 2008. Архивировано из оригинала 22 ноября 2008 года.
  3. musl - Introduction. www.musl-libc.org. Дата обращения: 30 января 2017. Архивировано 12 ноября 2020 года.

Дополнительные источники