Введение
Стандартная библиотека для языка программирования C
Стандартная библиотека C, или libc, — это стандартная библиотека для языка программирования C, как это определено в стандарте ISO C. Разработка библиотеки началась одновременно с оригинальным стандартом ANSI C и спецификацией POSIX библиотеки C, которая является его расширением. После принятия ANSI C Международной организацией по стандартизации, стандартная библиотека C также стала называться библиотекой ISO C. Стандартная библиотека C предоставляет макросы, определения типов и функции для решения таких задач, как работа со строками, математические вычисления, ввод-вывод, управление памятью и ряд других системных сервисов.
Файлы заголовка
Интерфейс прикладного программирования (API) стандартной библиотеки C объявлен в ряде файлов заголовков. Каждый файл заголовка содержит одно или несколько объявлений функций, определений типов данных и макросов. После длительного периода стабильности, три новых файла заголовков (iso646.h, wchar.h и wctype.h) были добавлены с Нормативным Дополнением 1 (ND1), дополнением к Стандарту C, ратифицированному в 1995 году. Еще шесть файлов заголовков (complex.h, fenv.h, inttypes.h, stdbool.h, stdint.h и tgmath.h) были добавлены с C99, пересмотром Стандарта C, опубликованным в 1999 году, и еще пять файлов (stdalign.h, stdatomic.h, stdnoreturn.h, threads.h и uchar.h) с C11 в 2011 году. Всего существует 29 файлов заголовков:
Name From Description <assert.h> Объявляет макрос assert, используемый для помощи в обнаружении логических ошибок и других типов ошибок при отладке программы. <complex.h> C99 Определяет набор функций для работы с комплексными числами. <ctype.h> Определяет набор функций, используемых для классификации символов по их типам или для преобразования между верхним и нижним регистром способом, независимым от используемого набора символов (обычно ASCII или одного из его расширений, хотя реализации, использующие EBCDIC, также известны). <errno.h> Для проверки кодов ошибок, сообщаемых библиотечными функциями. <fenv.h> C99 Определяет набор функций для управления окружением с плавающей точкой. <float.h> Определяет макроконстанты, определяющие специфичные для реализации свойства библиотеки с плавающей точкой. <inttypes.h> C99 Определяет целочисленные типы фиксированной ширины. <iso646.h> ND1 Определяет несколько макросов, реализующих альтернативные способы выражения нескольких стандартных токенов. Для программирования в наборах символов ISO 646. <limits.h> Определяет макроконстанты, определяющие специфичные для реализации свойства целочисленных типов. <locale.h> Определяет функции локализации. <math.h> Определяет общие математические функции. <setjmp.h> Объявляет макросы setjmp и longjmp, которые используются для нелокальных выходов. <signal.h> Определяет функции обработки сигналов. <stdalign.h> C11 Для запроса и указания выравнивания объектов. <stdarg.h> Для доступа к переменному числу аргументов, передаваемых функциям. <stdatomic.h> C11 Для атомарных операций с данными, совместно используемыми между потоками. <stdbool.h> C99 Определяет булев тип данных. <stddef.h> Определяет несколько полезных типов и макросов. <stdint.h> C99 Определяет целочисленные типы фиксированной ширины. <stdio.h> Определяет основные функции ввода и вывода. <stdlib.h> Определяет функции преобразования чисел, функции генерации псевдослучайных чисел, выделение памяти, функции управления процессами. <stdnoreturn.h> C11 Для указания функций, не возвращающих значения. <string.h> Определяет функции работы со строками. <tgmath.h> C99 Определяет типобезопасные математические функции. <threads.h> C11 Определяет функции для управления несколькими потоками, мьютексами и переменными условия. <time.h> Определяет функции работы с датой и временем. <uchar.h> C11 Типы и функции для работы с символами Unicode. <wchar.h> ND1 Определяет функции работы с широкими строками. <wctype.h> ND1 Определяет набор функций, используемых для классификации широких символов по их типам или для преобразования между верхним и нижним регистром.
Три файла заголовков (complex.h, stdatomic.h и threads.h) являются необязательными функциями, которые реализации не обязаны поддерживать. Стандарт POSIX добавил несколько нестандартных заголовков C для специфичных для Unix функций. Многие из них нашли применение в других архитектурах. Примеры включают fcntl.h и unistd.h. Ряд других групп используют другие нестандартные заголовки – библиотека GNU C имеет alloca.h, а OpenVMS имеет функцию va_count.
Документация
В Unix-подобных системах исчерпывающая документация по API предоставляется в виде man-страниц. На большинстве систем man-страницы по функциям стандартной библиотеки находятся в разделе 3, а раздел 7 может содержать более общие страницы, описывающие базовые концепции (например, man 7 math error в Linux).
Встроенные в компилятор функции
Некоторые компиляторы (например, GCC) предоставляют встроенные версии многих функций из стандартной библиотеки C; то есть, реализации этих функций записываются непосредственно в скомпилированный объектный файл, и программа вызывает встроенные версии вместо функций из разделяемой библиотеки C. Это снижает накладные расходы на вызов функций, особенно если вызовы заменяются встроенными (inline) вариантами, и позволяет применять другие виды оптимизации (поскольку компилятор знает особенности потока управления встроенных версий), но может затруднить отладку (например, встроенные версии нельзя заменить инструментаризованными). Однако встроенные функции должны вести себя как обычные функции в соответствии со стандартом ISO C. Главное следствие этого заключается в том, что программа должна иметь возможность создавать указатель на эти функции, получая их адрес, и вызывать функцию через этот указатель. Если два указателя на одну и ту же функцию получены в разных единицах трансляции программы, эти два указателя должны быть равны; то есть, адрес получается путем разрешения имени функции, имеющей внешнюю (программную) связь.
Связывание, libm
В FreeBSD и glibc некоторые функции, такие как sin, не подключаются по умолчанию и вместо этого поставляются в составе математической библиотеки libm. Если какие-либо из них используются, компоновщику необходимо передать директиву -lm. POSIX требует, чтобы компилятор c99 поддерживал -lm, и чтобы функции, объявленные в заголовочных файлах math.h, complex.h и fenv.h, были доступны для компоновки при указании -lm, но не определяет, подключаются ли эти функции по умолчанию. musl удовлетворяет этому требованию, помещая все в единую библиотеку libc и предоставляя пустую libm.
Обнаружение
Согласно стандарту C, макрос STDC HOSTED должен быть определен как 1, если реализация является хостируемой. Хостируемая реализация включает в себя все заголовочные файлы, указанные в стандарте C. Реализация также может быть автономной, что означает отсутствие этих заголовочных файлов. Если реализация является автономной, она должна определить STDC HOSTED как 0.
Проблемы с подводными лодками, уязвимость к условиям гонки
Функция strerror подвергается критике за небезопасность в многопоточной среде и подверженность гонкам данных.
Обработка ошибок
Обработка ошибок функций в стандартной библиотеке C непоследовательна и порой вызывает недоумение. Согласно странице руководства Linux по математическим ошибкам, "Текущая (версия 2.8) ситуация в glibc является хаотичной. Большинство (но не все) функций генерируют исключения при возникновении ошибок. Некоторые также устанавливают переменную errno. Несколько функций устанавливают errno, но не генерируют исключения. Лишь очень немногие функции не делают ни того, ни другого."
Стандартизация
Оригинальный язык C не предоставлял встроенных функций, таких как операции ввода-вывода, в отличие от традиционных языков, таких как COBOL и Fortran. Со временем сообщества пользователей C обменивались идеями и реализациями того, что сейчас известно как стандартные библиотеки C. Многие из этих идей в конечном итоге были включены в определение стандартизированного языка C. И Unix, и C были созданы в лабораториях Bell AT&T в конце 1960-х и начале 1970-х годов. В течение 1970-х годов язык C становился все более популярным. Многие университеты и организации начали разрабатывать собственные варианты языка для своих проектов. К началу 1980-х годов стали очевидны проблемы совместимости между различными реализациями C. В 1983 году Американский национальный институт стандартов (ANSI) сформировал комитет для разработки стандартной спецификации C, известной как "ANSI C". Эта работа завершилась созданием так называемого стандарта C89 в 1989 году. Частью полученного стандарта являлся набор программных библиотек, называемый стандартной библиотекой ANSI C.
Стандартная библиотека POSIX
POSIX, а также SUS, определяют ряд функций, которые должны быть доступны в дополнение к функциям базовой стандартной библиотеки C. Спецификация POSIX включает в себя файлы заголовков для, в частности, многопоточности, сетевого взаимодействия и регулярных выражений. Они часто реализуются совместно со стандартной библиотекой C, с разной степенью интеграции. Например, glibc реализует такие функции, как fork, внутри libc.so, но до объединения NPTL с glibc это была отдельная библиотека с собственным флагом компоновщика. Часто эта функциональность, определённая POSIX, рассматривается как часть библиотеки, а базовая библиотека C может называться библиотекой ANSI или ISO C.
Стандартная библиотека C на других языках
Некоторые языки включают функциональность стандартной библиотеки C в свои собственные библиотеки. Библиотека может быть адаптирована для лучшего соответствия структуре языка, но операционная семантика остаётся схожей. Например, язык C++ включает функциональность стандартной библиотеки C в пространство имён std (например, std::printf, std::atoi, std::feof), в заголовочных файлах с именами, аналогичными именам в C (cstdio, cmath, cstdlib и т. д.). Другие языки, использующие подобные подходы, — это D, Perl, Ruby и основная реализация Python, известная как CPython. В Python 2, например, встроенные объекты файлов определены как "реализованные с использованием пакета stdio языка C", поэтому ожидается, что доступные операции (открытие, чтение, запись и т. д.) будут вести себя так же, как соответствующие функции C. В Rust существует крейт, позволяющий использовать несколько функций C, структур и других определений типов.
Сравнение со стандартными библиотеками других языков
Стандартная библиотека C невелика по сравнению со стандартными библиотеками некоторых других языков. Библиотека C предоставляет базовый набор математических функций, операций над строками, преобразования типов, а также ввод-вывод для работы с файлами и консолью. Она не включает в себя стандартный набор "типов контейнеров", как, например, библиотека стандартных шаблонов C++, и тем более полные наборы инструментов графического пользовательского интерфейса (GUI), сетевые инструменты и широкий спектр других функций, которые Java и .NET Framework предоставляют по умолчанию. Главное преимущество небольшой стандартной библиотеки заключается в том, что создание рабочей среды ISO C значительно проще, чем для других языков, а следовательно, перенос C на новую платформу относительно легок.