¿Por qué las bibliotecas estándar no son primitivas de lenguaje de programación? [cerrado]


30

Estaba pensando por qué hay bibliotecas estándar (en todos los lenguajes de programación que he aprendido, como C ++, Java, Python) como stdlib, en lugar de tener "funciones" similares como primitivas del lenguaje en sí.


44
¿Qué quiere decir con "por qué el compilador no puede simplemente traducir una llamada a una función en un conjunto de instrucciones"? Eso es más o menos lo que hace el compilador, biblioteca estándar o no (Ok, Python solo a mitad de camino y Java a JVM bytecode; concepto similar). Las bibliotecas estándar realmente no tienen nada que ver con la compilación de código -> instrucciones.
Delioth

25
@Delioth Creo que Simone pregunta por qué no todo en la biblioteca estándar de lenguaje $ LANG es una construcción / función primitiva de ese lenguaje. Diría que es una pregunta razonable para cualquiera que sea muy nuevo en los lenguajes de programación :)
Andres F.

33
La biblioteca estándar generalmente llena la brecha entre un lenguaje de programación que funciona y uno útil que la gente usará.
Telastyn

66
Una parte importante de la biblioteca estándar de Python está realmente escrita en C y ya está compilada.
ElmoVanKielmo

1
Como una forma de contraste, en la mayoría de las implementaciones de BASIC todo es parte del lenguaje y no hay bibliotecas ni soporte para ellas (salvo, en varias implementaciones, la capacidad de llamar a rutinas de lenguaje de máquina).
Euro Micelli

Respuestas:


32

Permítanme ampliar un poco la buena respuesta de @ Vincent (+1) :

¿Por qué el compilador no puede simplemente traducir una llamada a una función en un conjunto de instrucciones?

Puede, y lo hace a través de al menos dos mecanismos:

  • alinear una llamada de función : durante la traducción, el compilador puede reemplazar una llamada de código fuente con su implementación directamente en línea en lugar de hacer una llamada real a la función. Aún así, la función necesita tener una implementación definida en algún lugar y que pueda estar en la biblioteca estándar.

  • función intrínseca: las funciones intrínsecas son funciones de las que se ha informado al compilador sin encontrar necesariamente la función en una biblioteca. Por lo general, están reservados para funciones de hardware a las que prácticamente no se puede acceder de otra manera, ya que son tan simples que incluso la sobrecarga de una función de biblioteca de llamadas al lenguaje ensamblador se considera alta. (El compilador generalmente solo puede insertar automáticamente el código fuente en su idioma, pero no las funciones de ensamblaje, que es donde entra el mecanismo intrínseco).

Aún así, la mejor opción a veces es que el compilador traduzca una llamada de función en el idioma de origen a una llamada de función en el código de máquina. La recursividad, los métodos virtuales y el gran tamaño son algunas de las razones por las cuales la alineación no siempre es posible / práctica. (Otra razón es la intención de la compilación, como la compilación separada (módulos de objeto), unidades de carga separadas (por ejemplo, DLL)).

Tampoco hay una ventaja real en hacer que la mayoría de las funciones estándar de la biblioteca sean intrínsecas (eso codificaría mucho más conocimiento en el compilador sin ninguna ventaja real), por lo que una llamada de código de máquina nuevamente es a menudo lo más apropiado.

C es un lenguaje notable que posiblemente omitió otras declaraciones de lenguaje explícito a favor de las funciones estándar de la biblioteca. Aunque las bibliotecas preexistieron, este lenguaje hizo un cambio para hacer más trabajo de las funciones estándar de la biblioteca y menos como declaraciones explícitas en la gramática del lenguaje. IO en otros lenguajes, por ejemplo, con frecuencia recibió su propia sintaxis en forma de varias declaraciones, mientras que la gramática C no define ninguna declaración IO, simplemente difiere a su biblioteca estándar para proporcionar eso, todo accesible a través de llamadas a funciones, que el compilador ya sabe cómo hacerlo.


3
Buena respuesta. Debería agregarse algunas palabras por las cuales se tomó esta decisión en C: si no recuerdo mal, la razón principal fue porque facilitó la creación de compiladores de C para muchas arquitecturas de hardware diferentes.
Doc Brown

10
@DocBrown Para 1975, había suficientes ejemplos en el área del desarrollo del lenguaje de programación (ALGOL-68, ¿alguien?) Que mostraran que los intentos de incorporar todo al lenguaje directamente condujeron a una desaceleración considerable tanto en el acabado de las especificaciones del lenguaje como en en la producción de implementaciones de lenguaje.
Joker_vD

55
Un ejemplo similar es con lo que hizo Python print: en 2.x, era una declaración , con su propia gramática especial, pero en 3.x, se convirtió en otra llamada de función. Ver PEP 3105 para la explicación oficial.
dan04

1
@DocBrown, la portabilidad casi seguramente no fue una razón. Cuando se crearon Unix y C, se diseñaron y construyeron para exactamente una máquina, una PDP-7 de repuesto, ya que Ken Thompson se preguntó qué conceptos podrían salvarse del fallido proyecto Multics. C también se creó por una razón: tener un lenguaje de alto nivel en el que (re) implementar Unix. Básicamente, somos un experimento en diseño de software, no un intento serio de un sistema operativo y lenguaje multiplataforma comercial. Ver bell-labs.com/usr/dmr/www/chist.html por ejemplo.
Euro Micelli

@EuroMicelli: No veo una contradicción. Y su referencia contiene muchos detalles sobre cuándo la portabilidad se volvió importante, en realidad fue en los primeros años del desarrollo de C y Unix. Solo puedo adivinar aquí, pero si los inventores de C no hubieran mantenido el lenguaje intencionalmente pequeño, creo que habría sido bastante improbable que pudieran haberlo portado tan rápido y con éxito a muchas arquitecturas diferentes.
Doc Brown

70

Esto es simplemente para mantener el lenguaje en sí lo más simple posible. Debe distinguir entre una característica del lenguaje, como un tipo de bucle o formas de pasar parámetros a funciones, etc., y la funcionalidad común que la mayoría de las aplicaciones necesitan.

Las bibliotecas son funciones que pueden ser útiles para muchos programadores, por lo que se crean como código reutilizable que se puede compartir. Las bibliotecas estándar están diseñadas para ser funciones muy comunes que los programadores suelen necesitar. De esta manera, el lenguaje de programación es inmediatamente útil para una gama más amplia de programadores. Las bibliotecas se pueden actualizar y ampliar sin cambiar las características principales del lenguaje en sí.


3
No siempre. PHPComo ejemplo, apenas hay diferencias entre sus vastas funciones del lenguaje y el lenguaje en sí.
Vahid Amiri

15
No tomaría PHP como ejemplo de un lenguaje simple
DrBreakalot

3
@DrBreakalot PHP es un lenguaje extremadamente simple. Eso no quiere decir que tenga un diseño consistente, pero ese es otro problema.
Lightness compite con Monica el

19
@LightnessRacesinOrbit No llamaría a PHP "simple" en absoluto: tiene un sistema de objetos basado en clases, un conjunto separado de 'valores primitivos', funciones independientes, cierres de primera clase integrados en el sistema de objetos, un mecanismo de espacio de nombres, varios nociones llamados "estática", declaraciones, así como expresiones, include, requirey require_once, si / for / while (programación estructurada), excepciones, un sistema separado de 'valores de error', complicada reglas de escritura débiles, complicada reglas de precedencia del operador, y así sucesivamente . Compare esto con la simplicidad de, por ejemplo, Smalltalk, Scheme, Prolog, Forth, etc.;)
Warbo

3
La razón principal, que se insinúa pero no se menciona explícitamente en esta respuesta, es que al mantener el lenguaje lo más simple posible, es mucho más fácil de implementar en otras plataformas. Dado que las bibliotecas estándar generalmente se escriben en el propio lenguaje , se pueden portar trivialmente.
BlueRaja - Danny Pflughoeft

34

Además de lo que las otras respuestas ya han dicho, poner funciones estándar en una biblioteca es una separación de preocupaciones :

  • El trabajo del compilador es analizar el idioma y generar código para él. No es el trabajo del compilador contener nada que ya pueda escribirse en ese idioma y proporcionarse como una biblioteca.

  • Es el trabajo de la biblioteca estándar (la que siempre está implícitamente disponible) para proporcionar la funcionalidad central que necesitan prácticamente todos los programas. No es el trabajo de la biblioteca estándar contener todas las funciones que podrían ser útiles.

  • El trabajo de las bibliotecas estándar opcionales es proporcionar una funcionalidad auxiliar que muchos programas pueden prescindir, pero que siguen siendo bastante básicas y también esenciales para que muchas aplicaciones garanticen el envío con entornos estándar. No es el trabajo de esas bibliotecas opcionales contener todo el código reutilizable que se haya escrito.

  • El trabajo de las bibliotecas de usuario es proporcionar colecciones de funciones útiles reutilizables. No es el trabajo de las bibliotecas de usuario contener todo el código que se ha escrito.

  • El trabajo del código fuente de una aplicación es proporcionar los bits de código restantes que en realidad solo son relevantes para esa aplicación.

Si quieres un software único para todos, obtienes algo increíblemente complejo. Necesita modularizar para reducir la complejidad a niveles manejables. Y necesita modularizar para permitir implementaciones parciales :

  • La biblioteca de subprocesos no tiene valor en el controlador integrado de un solo núcleo. Permitir que la implementación del lenguaje para este controlador integrado simplemente no incluya la pthreadbiblioteca es lo correcto.

  • La biblioteca matemática no tiene valor en el microcontrolador que ni siquiera tiene una FPU. Nuevamente, no verse obligado a proporcionar funciones como sin()hace la vida mucho más fácil para los implementadores de su lenguaje para ese microcontrolador.

  • Incluso la biblioteca estándar central no tiene valor cuando está programando un núcleo. No puede implementar write()sin una syscall en el kernel, y no puede implementar printf()sin write(). Como programador de kernel, es su trabajo proporcionar la write()llamada al sistema, no puede esperar que esté allí.

Un lenguaje que no permite tales omisiones de las bibliotecas estándar simplemente no es adecuado para muchas tareas . Si desea que su idioma sea flexiblemente utilizable en entornos poco comunes, debe ser flexible en las bibliotecas estándar que se incluyen. Cuanto más se base su lenguaje en las bibliotecas estándar, más suposiciones hará sobre su entorno de ejecución y, por lo tanto, restringirá su uso a entornos que brinden estos requisitos previos.

Por supuesto, los lenguajes de alto nivel como Python y Java pueden hacer muchas suposiciones sobre su entorno. Y tienden a incluir muchas cosas en sus bibliotecas estándar. Los lenguajes de nivel inferior como C proporcionan mucho menos en sus bibliotecas estándar y mantienen la biblioteca estándar central mucho más pequeña. Es por eso que encuentra un compilador de C que funciona para prácticamente cualquier arquitectura, pero es posible que no pueda ejecutar ningún script de Python en él.


16

Una razón importante por la que los compiladores y las bibliotecas estándar están separadas es porque tienen dos propósitos diferentes (incluso si ambos están definidos por la misma especificación de lenguaje): el compilador traduce el código de nivel superior en instrucciones de máquina, y la biblioteca estándar proporciona pruebas previamente implementaciones de funcionalidad comúnmente necesaria. Los escritores de compiladores valoran la modularidad al igual que otros desarrolladores de software. De hecho, algunos de los primeros compiladores de C dividieron aún más el compilador en programas separados para preprocesar, compilar y vincular.

Esta modularidad le ofrece muchas ventajas:

  • Reduce al mínimo la cantidad de trabajo necesario cuando se admite una nueva plataforma de hardware, ya que la mayoría del código de biblioteca estándar es independiente del hardware y se puede reutilizar.
  • Una implementación de biblioteca estándar se puede optimizar de diferentes maneras (por velocidad, por espacio, por uso de recursos, etc.). Muchos de los primeros sistemas informáticos solo tenían un compilador disponible, y tener una biblioteca estándar separada significaba que los desarrolladores podían intercambiar implementaciones para satisfacer sus necesidades.
  • La funcionalidad de la biblioteca estándar ni siquiera tiene que existir. Por ejemplo, al escribir código C sin formato, tiene un compilador con todas las funciones, pero la mayor parte de la funcionalidad estándar de la biblioteca no está presente y algunas cosas como la E / S de archivos ni siquiera son posibles. Si se requirió que el compilador implementara esta funcionalidad, entonces no podría tener un compilador C que cumpla con los estándares en algunas de las plataformas donde más lo necesita.
  • En los primeros sistemas, los compiladores fueron desarrollados frecuentemente por la compañía que diseñó el hardware. El proveedor del sistema operativo proporcionaba con frecuencia bibliotecas estándar, ya que a menudo requerían acceso a funcionalidades (como llamadas al sistema) específicas de esa plataforma de software. No era práctico para un escritor compilador tener que soportar todas las diferentes combinaciones de hardware y software (solía haber mucha más variedad tanto en arquitectura de hardware como en plataforma de software).
  • En lenguajes de alto nivel, se puede implementar una biblioteca estándar como una biblioteca cargada dinámicamente. Una implementación de biblioteca estándar puede ser utilizada por múltiples compiladores y / o lenguajes de programación.

Históricamente hablando (al menos desde la perspectiva de C), las versiones originales de pre-estandarización del lenguaje no tenían una biblioteca estándar en absoluto. Los proveedores de sistemas operativos y terceros a menudo proporcionarían bibliotecas llenas de funcionalidades de uso común, pero diferentes implementaciones incluían cosas diferentes y eran en gran medida incompatibles entre sí. Cuando C se estandarizó, definieron una "biblioteca estándar" en un intento de armonizar estas implementaciones dispares y mejorar la portabilidad. La biblioteca estándar C se desarrolló por separado del lenguaje, como las bibliotecas Boost para C ++, pero luego se integraron en la especificación del lenguaje.


6

Respuesta adicional de caso de esquina: gestión de propiedad intelectual

Un ejemplo notable es la implementación de Math.Pow (doble, doble) en .NET Framework que Microsoft compró a Intel y sigue sin divulgarse incluso si el marco fue de código abierto. (Para ser precisos, en el caso anterior es una llamada interna en lugar de una biblioteca, pero la idea es válida). Una biblioteca separada del lenguaje en sí (teóricamente también un subconjunto de bibliotecas estándar) puede dar a los patrocinadores del lenguaje más flexibilidad para dibujar el línea entre lo que debe mantenerse transparente y lo que debe permanecer sin revelar (debido a sus contratos con terceros u otros motivos relacionados con la propiedad intelectual).


Esto es confuso. La página a la que se vincula Math.Powno menciona ninguna compra, ni nada sobre Intel, y habla de personas que leen el código fuente de la implementación de la función.
Lightness compite con Monica el

@LightnessRacesinOrbit - hm, todavía puedo verlo allí (cuando busco "intel"). También puede encontrar la referencia al código fuente reciente (en los comentarios más recientes) y también una implementación alternativa (en la segunda respuesta) que está disponible públicamente pero la complejidad y la ineficacia comentada de las cuales dan una pista de por qué la implementación original aún no se revela. Una implementación verdaderamente eficiente puede requerir un conocimiento profundo de muchos detalles sobre el nivel de CPU que no están necesariamente disponibles en el dominio público.
miroxlav

5

Errores y depuración.

Errores: todo el software tiene errores, su biblioteca estándar tiene errores y su compilador tiene errores. Como usuario del lenguaje, es mucho más fácil encontrar y solucionar estos errores cuando están en la biblioteca estándar en lugar de en el compilador.

Depuración: es mucho más fácil para mí ver un seguimiento de la pila de una biblioteca estándar y darme una idea de lo que podría estar yendo mal. Porque ese rastro de pila tiene código, entiendo. Por supuesto, puede profundizar más y también puede rastrear sus funciones intrínsecas, pero es mucho más fácil si está en un idioma que usa todo el tiempo día a día.


5

Esta es una excelente pregunta!

Lo último

El estándar C ++, por ejemplo, nunca especifica qué se debe implementar en el compilador o en la biblioteca estándar: solo se refiere a la implementación . Por ejemplo, los símbolos reservados están definidos tanto por el compilador (como intrínsecos) como por la biblioteca estándar, indistintamente.

Sin embargo, todas las implementaciones de C ++ que conozco tendrán el mínimo número posible de intrínsecos proporcionados por el compilador, y tanto como sea posible por la biblioteca estándar.

Por lo tanto, si bien es técnicamente factible definir la biblioteca estándar como una funcionalidad intrínseca en el compilador, parece que rara vez se usa en la práctica.

¿Por qué?

Consideremos la idea de mover alguna pieza de funcionalidad de la biblioteca estándar al compilador.

Ventajas:

  • Mejores diagnósticos: los intrínsecos pueden tener una carcasa especial.
  • Mejor rendimiento: los intrínsecos pueden tener una carcasa especial.

Desventajas

  • Mayor masa del compilador: cada caso especial agrega complejidad al compilador; la complejidad aumenta los costos de mantenimiento y la probabilidad de errores.
  • Una iteración más lenta: cambiar la implementación de la funcionalidad requiere cambiar el compilador en sí, lo que dificulta la creación de una pequeña biblioteca (fuera de std) para experimentar.
  • Barras de entrada más altas: cuanto más costoso / más difícil es cambiar algo, es menos probable que la gente intervenga.

Esto significa que mover algo al compilador es costoso , ahora y en el futuro, y por lo tanto requiere un caso sólido. Para algunas piezas de funcionalidad, es necesario (no se pueden escribir como código regular), sin embargo, incluso así, vale la pena extraer piezas mínimas y genéricas para pasar al compilador y construir sobre ellas en la biblioteca estándar.


5

Como diseñador de idiomas, me gustaría hacerme eco de algunas de las otras respuestas aquí, pero proporcionarlo a través de los ojos de alguien que está construyendo un idioma.

Una API no finaliza cuando termina de agregar todo lo que puede en ella. Una API finaliza cuando haya terminado de sacar todo lo que pueda de ella.

Se debe especificar un lenguaje de programación utilizando algún lenguaje. Debe poder transmitir el significado detrás de cualquier programa escrito en su idioma. Este lenguaje es muy difícil de escribir, y aún más difícil de escribir bien. En general, tiende a ser una forma de inglés muy precisa y bien estructurada que se utiliza para transmitir significado no a la computadora, sino a otros desarrolladores, especialmente aquellos desarrolladores que escriben compiladores o intérpretes para su idioma. Aquí hay un ejemplo de la especificación C ++ 11, [intro.multithread / 14]:

La secuencia visible de efectos secundarios en un objeto atómico M, con respecto a un cálculo de valor B de M, es una subsecuencia contigua máxima de efectos secundarios en el orden de modificación de M, donde el primer efecto secundario es visible con respecto a B , y para cada efecto secundario, no es el caso de que B ocurra antes. El valor de un objeto atómico M, según lo determinado por la evaluación B, será el valor almacenado por alguna operación en la secuencia visible de M con respecto a B. [Nota: se puede demostrar que la secuencia visible de los efectos secundarios de un valor El cálculo es único dados los requisitos de coherencia a continuación. —Nota final]

Blek! Cualquiera que se haya lanzado a comprender cómo C ++ 11 maneja el subprocesamiento múltiple puede apreciar por qué la redacción debe ser tan opaca, pero eso no perdona el hecho de que es ... bueno ... ¡tan opaco!

Compare eso con la definición de std::shared_ptr<T>::reset, en la sección de la biblioteca del estándar:

template <class Y> void reset(Y* p);

Efectos: equivalentes ashared_ptr(p).swap(*this)

Entonces, ¿cuál es la diferencia? En la parte de definición del lenguaje, los escritores no pueden asumir que el lector comprende las primitivas del lenguaje. Todo debe especificarse cuidadosamente en prosa inglesa. Una vez que llegamos a la parte de definición de la biblioteca, podemos usar el lenguaje para especificar el comportamiento. ¡Esto es a menudo mucho más fácil!

En principio, uno podría tener una construcción suave a partir de primitivas al comienzo del documento de especificaciones, hasta definir lo que podríamos considerar como "características de biblioteca estándar", sin tener que trazar una línea entre "primitivas de lenguaje" y características de "biblioteca estándar". En la práctica, esa línea resulta enormemente valiosa de dibujar porque le permite escribir algunas de las partes más complejas del lenguaje (como las que deben implementar algoritmos) utilizando un lenguaje diseñado para expresarlas.

Y de hecho, vemos algunas líneas borrosas:

  • En Java, solojava.lang.ref.Reference<T> pueden ser subclasificadas por las clases de biblioteca estándar y porque los comportamientos de están tan profundamente entrelazados con la especificación del lenguaje Java que debieron poner algunas restricciones en la parte de ese proceso implementado como clases de "biblioteca estándar".java.lang.ref.WeakReference<T> java.lang.ref.SoftReference<T>java.lang.ref.PhantomReference<T>Reference
  • En C #, hay una clase, System.Delegate que encapsula el concepto de delegados. A pesar de su nombre, no es un delegado. También es una clase abstracta (no puede ser instanciada) de la que no puede crear clases derivadas. Solo el sistema puede hacerlo a través de características escritas en la especificación del lenguaje.

2

Esto se entiende como una adición a las respuestas existentes (y es demasiado largo para un comentario).

Existen al menos otras dos razones para una biblioteca estándar:

Barrera de entrada

Si una característica de idioma en particular está en una función de biblioteca y quiero saber cómo funciona, puedo leer la fuente de esa función. Si deseo enviar un informe de error / solicitud de parche / extracción, generalmente no es demasiado difícil codificar una solución y probar los casos. Si está en el compilador, tengo que poder profundizar en lo interno. Incluso si está en el mismo idioma (y debería estarlo, cualquier compilador que se respete a sí mismo debería ser autohospedado) el código del compilador no se parece en nada al código de la aplicación. Puede llevar una eternidad incluso encontrar los archivos correctos.

Te estás desconectando de muchos contribuyentes potenciales si sigues esa ruta.

Carga de código caliente

Muchos idiomas ofrecen esta característica en un grado u otro, pero sería enormemente complicado volver a cargar en caliente el código que está haciendo la recarga en caliente. Si el SL está separado del tiempo de ejecución, se puede volver a cargar.


3
"cualquier compilador que se precie debe ser autohospedado", en absoluto. Sería inútil tener versiones de digamos LLVM escritas en C, C ++, Objective-C, Swift, Fortran, etc. para compilar todos estos lenguajes.
gnasher729

@ gnasher729 ¿no es un caso especial (junto con otros objetivos multilingües como el CLR)?
Jared Smith

@JaredSmith Diría que ahora es el caso general, no especial en absoluto. Ya nadie escribe "un compilador" como una aplicación monolítica. Producen sistemas compiladores en su lugar. La mayor parte de la funcionalidad del compilador completa es totalmente independiente de la lengua particular que se está elaborando, y gran parte de la parte que depende del idioma se puede hacer mediante el suministro de diferentes datos que definen la gramática de la lengua, no escribiendo diferentes códigos para cada idioma que Quiero compilar.
alephzero

2

Esta es una pregunta interesante, pero ya hay muchas buenas respuestas, así que no intentaré una completa.

Sin embargo, dos cosas que no creo que hayan recibido suficiente atención:

Primero es que no todo está muy claro. Es un poco de espectro exactamente porque hay razones para hacer las cosas de manera diferente. Como ejemplo, los compiladores a menudo conocen las bibliotecas estándar y sus funciones. Ejemplo del ejemplo: la función "Hello World" de C, printf, es la mejor que se me ocurre. Es una función de biblioteca, tiene que ser así, ya que depende mucho de la plataforma. Pero el compilador debe conocer su comportamiento (implementación definida) para advertir al programador sobre invocaciones incorrectas. Esto no es particularmente bueno, pero fue visto como un buen compromiso. Por cierto, esta es la respuesta real a la mayoría de las preguntas de "por qué este diseño": mucho compromiso y "parecía una buena idea en ese momento". No siempre el "esta era la forma clara de hacerlo" o "

En segundo lugar, permite que la biblioteca estándar no sea tan estándar. Hay muchas situaciones en las que un lenguaje es deseable, pero las bibliotecas estándar que generalmente lo acompañan no son prácticas y deseables. Este es el caso más común con lenguajes de programación de sistemas como C, en plataformas no estándar. Por ejemplo, si tiene un sistema sin un sistema operativo o un planificador: no tendrá subprocesos.

Con un modelo de biblioteca estándar (y los subprocesos son compatibles), esto se puede manejar de manera limpia: el compilador es prácticamente el mismo, puede reutilizar los bits de las bibliotecas que se aplican, y todo lo que no se puede eliminar. Si esto se incluye en el compilador, las cosas comienzan a complicarse.

Por ejemplo:

  • No puedes ser un compilador compatible.

  • ¿Cómo indicaría su desviación del estándar? Tenga en cuenta que generalmente hay alguna forma de sintaxis de importación / inclusión que puede tener un error, es decir, la importación de pitones o la inclusión de C que apunta fácilmente al problema si falta algo en el modelo de biblioteca estándar.

También se aplican problemas similares si desea modificar o ampliar la funcionalidad de 'biblioteca'. Esto es mucho más común de lo que piensas. Solo para seguir con el enhebrado: Windows, Linux y algunas unidades de procesamiento de red exóticas hacen el enhebrado de manera muy diferente. Si bien los bits de Linux / Windows pueden ser bastante estáticos y poder usar una API idéntica, las cosas de la NPU cambiarán con el día de la semana y la API con ella. Los compiladores se desviarían rápidamente a medida que la gente decidiera qué partes necesitaban soportar / podrían hacer con bastante rapidez si no había forma de dividir este tipo de cosas.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.