La biblioteca estándar C o libc es la biblioteca estándar para el lenguaje de programación C , tal y como se especifica en el estándar ISO C. [1] A partir del estándar ANSI C original , se desarrolló al mismo tiempo que la especificación POSIX de la biblioteca C , que es un superconjunto del mismo. [2] [3] Dado que ANSI C fue adoptado por la Organización Internacional de Normalización , [4] la biblioteca estándar C también se llama biblioteca ISO C.
La biblioteca estándar C proporciona macros , definiciones de tipos y funciones para tareas como manejo de cadenas , cálculos matemáticos, procesamiento de entrada/salida, administración de memoria y varios otros servicios del sistema operativo .
La interfaz de programación de aplicaciones (API) de la biblioteca estándar C se declara en varios archivos de encabezado . Cada archivo de encabezado contiene una o más declaraciones de funciones, definiciones de tipos de datos y macros.
Después de un largo período de estabilidad, se agregaron tres nuevos archivos de encabezado ( , y ) con iso646.h
el wchar.h
Anexo Normativo 1 (NA1), una adición al Estándar C ratificado en 1995. Se agregaron seis archivos de encabezado más ( ,,,,, y ) con C99 , una revisión del estándar C publicada en 1999, y cinco archivos más ( ,,, y ) con C11 en 2011. En total, ahora hay 29 archivos de encabezado:wctype.h
complex.h
fenv.h
inttypes.h
stdbool.h
stdint.h
tgmath.h
stdalign.h
stdatomic.h
stdnoreturn.h
threads.h
uchar.h
Tres de los archivos de encabezado ( complex.h
, stdatomic.h
y threads.h
) son características condicionales que no es necesario que las implementaciones admitan.
El estándar POSIX agregó varios encabezados C no estándar para funciones específicas de Unix. Muchos han encontrado su camino hacia otras arquitecturas. Los ejemplos incluyen fcntl.h
y unistd.h
. Varios otros grupos están utilizando otros encabezados no estándar: la biblioteca GNU C tiene alloca.h
y OpenVMS tiene la va_count()
función.
En sistemas tipo Unix, la documentación autorizada de la API se proporciona en forma de páginas de manual . En la mayoría de los sistemas, las páginas de manual sobre funciones de biblioteca estándar se encuentran en la sección 3; La sección 7 puede contener algunas páginas más genéricas sobre conceptos subyacentes (por ejemplo, man 7 math_error
en Linux ).
Los sistemas tipo Unix normalmente tienen una biblioteca C en forma de biblioteca compartida , pero los archivos de encabezado (y la cadena de herramientas del compilador) pueden estar ausentes en una instalación, por lo que el desarrollo en C puede no ser posible. La biblioteca C se considera parte del sistema operativo en sistemas tipo Unix; Además de las funciones especificadas por el estándar C, incluye otras funciones que forman parte de la API del sistema operativo, como las funciones especificadas en el estándar POSIX . Las funciones de la biblioteca C, incluidas las del estándar ISO C, son ampliamente utilizadas por los programas y se consideran como si no sólo fueran una implementación de algo en el lenguaje C, sino también parte de facto de la interfaz del sistema operativo. Los sistemas operativos tipo Unix generalmente no pueden funcionar si se borra la biblioteca C. Esto es cierto para aplicaciones que están vinculadas dinámicamente en lugar de estáticamente. Además, el propio núcleo (al menos en el caso de Linux) funciona independientemente de cualquier biblioteca.
En Microsoft Windows, las bibliotecas dinámicas del sistema central ( DLL ) proporcionan una implementación de la biblioteca estándar C para el compilador Microsoft Visual C++ v6.0; La biblioteca estándar C para las versiones más recientes del compilador Microsoft Visual C++ la proporciona cada compilador individualmente, así como paquetes redistribuibles . Las aplicaciones compiladas escritas en C están vinculadas estáticamente a una biblioteca de C o a una versión dinámica de la biblioteca que se envía con estas aplicaciones, en lugar de depender de su presencia en los sistemas de destino. Las funciones de la biblioteca C de un compilador no se consideran interfaces para Microsoft Windows.
Existen muchas implementaciones de bibliotecas de C, provistas de varios sistemas operativos y compiladores de C. Algunas de las implementaciones populares son las siguientes:
Algunos compiladores (por ejemplo, GCC [7] ) proporcionan versiones integradas de muchas de las funciones de la biblioteca estándar de C; es decir, las implementaciones de las funciones se escriben en el archivo objeto compilado y el programa llama a las versiones integradas en lugar de a las funciones en el archivo objeto compartido de la biblioteca C. Esto reduce la sobrecarga de llamadas a funciones, especialmente si las llamadas a funciones se reemplazan con variantes en línea , y permite otras formas de optimización (ya que el compilador conoce las características de flujo de control de las variantes integradas), pero puede causar confusión al depurar (por ejemplo , las versiones integradas no se pueden sustituir por variantes instrumentadas ).
Sin embargo, las funciones integradas deben comportarse como funciones ordinarias de acuerdo con ISO C. La principal implicación es que el programa debe poder crear un puntero a estas funciones tomando su dirección e invocar la función mediante ese puntero. Si dos punteros a la misma función se derivan en dos unidades de traducción diferentes en el programa, estos dos punteros deben compararse iguales; es decir, la dirección se obtiene resolviendo el nombre de la función, que tiene un vínculo externo (para todo el programa).
En FreeBSD [8] y glibc, [9] algunas funciones como sin() no están vinculadas de forma predeterminada y, en cambio, están incluidas en la biblioteca matemática libm . Si se utiliza alguno de ellos, se debe dar la directiva al enlazador -lm
. POSIX requiere que el compilador c99 admita -lm
y que las funciones declaradas en los encabezados math.h
, complex.h
y fenv.h
estén disponibles para vincularse si -lm
se especifica, pero no especifica si las funciones están vinculadas de forma predeterminada. [10] musl satisface este requisito poniendo todo en una única biblioteca libc y proporcionando una libm vacía. [11]
Según el estándar C, la macro __STDC_HOSTED__
se definirá en 1 si la implementación está alojada. Una implementación alojada tiene todos los encabezados especificados por el estándar C. Una implementación también puede ser independiente, lo que significa que estos encabezados no estarán presentes. Si una implementación es independiente , se definirá __STDC_HOSTED__
en 0 .
Algunas funciones de la biblioteca estándar de C han sido conocidas por tener vulnerabilidades de desbordamiento del búfer y, en general, fomentar la programación con errores desde su adopción. [a] Los ítems más criticados son:
strcpy()
y strcat()
, por falta de verificación de límites y posibles desbordamientos del búfer si los límites no se verifican manualmente;printf()
familia de rutinas, para estropear la pila de ejecución cuando la cadena de formato no coincide con los argumentos dados. Este defecto fundamental creó toda una clase de ataques: ataques de formato de cadena ;gets()
y scanf()
familia de rutinas de E/S, por falta de (ya sea cualquiera o fácil) verificación de la longitud de entrada.Excepto en el caso extremo de gets()
, todas las vulnerabilidades de seguridad se pueden evitar introduciendo código auxiliar para realizar gestión de memoria, verificación de límites, verificación de entradas, etc. Esto a menudo se hace en forma de contenedores que hacen que las funciones de biblioteca estándar sean más seguras y fáciles de usar. Esto se remonta al libro The Practice of Programming de B. Kernighan y R. Pike, donde los autores suelen utilizar envoltorios que imprimen mensajes de error y cierran el programa si se produce un error.
El comité ISO C publicó los informes técnicos TR 24731-1 [12] y está trabajando en TR 24731-2 [13] para proponer la adopción de algunas funciones con verificación de límites y asignación automática de buffer, respectivamente. El primero ha recibido severas críticas y algunos elogios, [14] [15] el segundo recibió respuestas mixtas. A pesar de esto, TR 24731-1 se ha implementado en la biblioteca estándar C de Microsoft y su compilador emite advertencias cuando se utilizan funciones antiguas "inseguras".
La strerror()
rutina es criticada por ser insegura y vulnerable a las condiciones de carrera .
El tratamiento de errores de las funciones de la biblioteca estándar de C no es coherente y, a veces, confuso. Según la página del manual de Linux math_error
, "La situación actual (versión 2.8) bajo glibc es complicada. La mayoría de las funciones (pero no todas) generan excepciones en caso de errores. Algunas también configuran errno . Algunas funciones configuran errno , pero no generan una excepción. Muy pocas funciones no hacen ninguna de las dos cosas." [dieciséis]
El lenguaje C original no proporcionaba funciones integradas como operaciones de E/S, a diferencia de los lenguajes tradicionales como COBOL y Fortran . [ cita necesaria ] Con el tiempo, las comunidades de usuarios de C compartieron ideas e implementaciones de lo que ahora se llama bibliotecas estándar de C. Muchas de estas ideas finalmente se incorporaron a la definición del lenguaje C estandarizado.
Tanto Unix como C fueron creados en los Laboratorios Bell de AT&T a finales de los años 1960 y principios de los 1970. Durante la década de 1970, el lenguaje C se hizo cada vez más popular. Muchas universidades y organizaciones comenzaron a crear sus propias variantes del idioma para sus propios proyectos. A principios de la década de 1980 se hicieron evidentes los problemas de compatibilidad entre las distintas implementaciones de C. En 1983, el Instituto Nacional Estadounidense de Estándares (ANSI) formó un comité para establecer una especificación estándar de C conocida como " ANSI C ". Este trabajo culminó con la creación del llamado estándar C89 en 1989. Parte del estándar resultante fue un conjunto de bibliotecas de software llamado biblioteca estándar ANSI C.
POSIX , así como SUS , especifican una serie de rutinas que deberían estar disponibles además de las de la biblioteca estándar básica de C. La especificación POSIX incluye archivos de encabezado para, entre otros usos, subprocesos múltiples , redes y expresiones regulares . A menudo se implementan junto con la funcionalidad de la biblioteca estándar de C, con distintos grados de similitud. Por ejemplo, glibc implementa funciones como fork
inside libc.so
, pero antes de que NPTL se fusionara con glibc, constituía una biblioteca separada con su propio argumento de indicador de enlazador. A menudo, esta funcionalidad especificada por POSIX se considerará parte de la biblioteca; la biblioteca C básica puede identificarse como biblioteca ANSI o ISO C.
BSD libc es un superconjunto de la biblioteca estándar POSIX compatible con las bibliotecas C incluidas con los sistemas operativos BSD como FreeBSD , NetBSD , OpenBSD y macOS . BSD libc tiene algunas extensiones que no están definidas en el estándar original, muchas de las cuales aparecieron por primera vez en la versión 4.4BSD de 1994 (la primera que se desarrolló en gran medida después de que se publicara el primer estándar en 1989). Algunas de las extensiones de BSD libc son:
sys/tree.h
– contiene una implementación de árbol rojo-negro y árbol splay [17] [18]sys/queue.h
– implementaciones de lista enlazada , colas , cola de cola, etc. [19] [20]fgetln()
– definido en stdio.h
. Esto se puede utilizar para leer un archivo línea por línea. [21] [22] [23]fts.h
– contiene algunas funciones para recorrer una jerarquía de archivos [24] [25]db.h
– algunas funciones para conectarse a la base de datos Berkeley [26] [27]strlcat()
y strlcpy()
– alternativas seguras para strncat()
y strncpy()
[28] [29] [30] [31] [32]err.h
– contiene algunas funciones para imprimir mensajes de error formateados [33] [34]vis.h
– contiene la vis()
función. Esta función se utiliza para mostrar caracteres no imprimibles en un formato visual. [35] [36] [37]Algunos lenguajes incluyen la funcionalidad de la biblioteca C estándar en sus propias bibliotecas. La biblioteca puede adaptarse para adaptarse mejor a la estructura del lenguaje, pero la semántica operativa se mantiene similar. El lenguaje C++ , por ejemplo, incluye la funcionalidad de la biblioteca estándar de C en el espacio de nombres std
(p. ej., std::printf
, std::atoi
, std::feof
), en archivos de cabecera con nombres similares a los de C ( cstdio
, cmath
, cstdlib
, etc.). Otros lenguajes que adoptan enfoques similares son D , Perl , Ruby y la implementación principal de Python conocida como CPython . En Python 2, por ejemplo, los objetos de archivo integrados se definen como "implementados usando el stdio
paquete C", [38] de modo que se espera que las operaciones disponibles (abrir, leer, escribir, etc.) tengan el mismo comportamiento que las funciones C correspondientes. Rust tiene una caja llamada libc que permite utilizar varias funciones, estructuras y otras definiciones de tipos de C. [39]
La biblioteca estándar de C es pequeña en comparación con las bibliotecas estándar de otros lenguajes. La biblioteca C proporciona un conjunto básico de funciones matemáticas, manipulación de cadenas, conversiones de tipos y E/S basadas en archivos y consola. No incluye un conjunto estándar de " tipos de contenedores " como la Biblioteca de plantillas estándar de C++ , y mucho menos los kits completos de herramientas de interfaz gráfica de usuario (GUI), herramientas de red y la profusión de otras funciones que Java y .NET Framework proporcionan como estándar. La principal ventaja de la pequeña biblioteca estándar es que proporcionar un entorno ISO C funcional es mucho más fácil que con otros lenguajes y, en consecuencia, portar C a una nueva plataforma es comparativamente fácil.
gets()
creó ya en 1988.