Muchos proyectos C++ (por ejemplo, muchas bibliotecas Boost
) son "solo encabezados".Vinculación solo de encabezado
¿Esto también es posible en el C
? ¿Cómo poner el código fuente en los encabezados? ¿Hay algún sitio al respecto?
Muchos proyectos C++ (por ejemplo, muchas bibliotecas Boost
) son "solo encabezados".Vinculación solo de encabezado
¿Esto también es posible en el C
? ¿Cómo poner el código fuente en los encabezados? ¿Hay algún sitio al respecto?
Resumen ejecutivo: Puede, pero no debe.
C y el código C++ es preprocesados antes de que sea compilada: todas las cabeceras se "pegan" en los archivos fuente que los incluyen, de forma recursiva. Si define una función en un encabezado y está incluida en dos archivos C, terminará con dos copias en cada archivo de objeto (violación One Definition Rule).
Puede crear bibliotecas C "solo encabezado" si todas sus funciones están marcadas como static
, es decir, no visibles fuera de la unidad de traducción. Pero también significa que obtendrá una copia de todas las funciones estáticas en cada unidad de traducción que incluye el archivo de encabezado.
Es un poco diferente en C++: las funciones en línea no son static
, los símbolos emitidos por el compilador aún son visibles por el vinculador, pero el vinculador puede descartar duplicados, en lugar de abandonar (símbolos "débiles").
No es idiomático escribir código C en los encabezados, a menos que esté basado en macros (por ejemplo, queue(3)
). En C++, la razón principal para mantener el código en los encabezados son las plantillas, que pueden dar lugar a la creación de instancias de código para diferentes parámetros de plantilla, que no es aplicable a C.
+1: Cubre casi todas las bases, creo. –
No enlaza los encabezados.
En C++ es un poco más fácil escribir código que ya está mejor en los encabezados que en los módulos compilados por separado porque las plantillas lo requieren.
Pero también puede utilizar la palabra clave inline
para funciones, que existe tanto en C como en C++.
// Won't cause redefinition link errors, because of 6.7.4/5
inline void foo(void) {
// ...
}
[c99: 6.7.4/5:]
Una función declarada con unainline
función especificador es una función inline. El especificador de función puede aparecer más de una vez; el comportamiento es el mismo que si solo apareciera una vez. Hacer que una función sea una función en línea sugiere que las llamadas a la función sean lo más rápidas posible. El grado en que dichas sugerencias son efectivas está definido por la implementación.
Sin embargo, estás un poco atascado cuando se trata de objetos de datos.
- Algo así.
- C99 seguro. C89/C90 Tendría que verificar.
¿Quisiste decir static keyword? Porque en línea es solo una recomendación para el compilador y se puede ignorar por completo. – Cartesius00
@James: No, quise decir 'en línea'. Aunque 'en línea' es solo una pista y el compilador no necesita alinear físicamente la función, el efecto que tiene en el enlace de la función está bien definido y debe ser observado por una implementación. De lo contrario, ¿cómo podrías saber qué vinculación tenía tu función 'inline'? –
Oh, ya veo, es diferente en C vs. C++, ¿no? – Cartesius00
Boost hace uso de plantillas pesada y plantilla de meta-programación que no se puede emular (todos los que fácilmente) en C.
Pero por supuesto puede engañar al tener declaraciones y códigos en las cabeceras de C, que se #include
, sino que es no es lo mismo Yo diría "Cuando esté en Roma ..." y el programa C según las convenciones de C con bibliotecas.
El "Cuando en Roma ..." me parece una gran respuesta. Gracias :) – Cartesius00
Me alegro de ser de ayuda. No dude en aceptarlo también, siempre que aún lo vea como la mejor respuesta al momento de revisar. –
Sí, es muy posible. Declare todas las funciones en los encabezados y, o bien todas como static
o simplemente use una sola unidad de compilación (es decir, un solo archivo c) en sus proyectos.
Como anécdota personal, sé un buen número de físicos que insisten en que esta técnica es la única manera verdadera de programa C. Es beneficioso porque es la versión de los pobres de -fwhole-program
, es decir, hace optimizaciones basadas en el conocimiento de comportamiento de la función posible. Es práctico porque no necesita aprender sobre el uso de las banderas del enlazador. Es una mala idea porque todo el programa debe compilarse como un todo y volver a compilarse con cada cambio menor.
Personalmente, recomendaría dejarlo o al menos ir con static
por solo unas pocas funciones.
La respuesta no señala el agujero evidente con este enfoque. –
@ TomalakGeret'kal: ¿Cuál de los agujeros deslumbrantes? – thiton
'static' le da copias por TU. Realmente, los agujeros que todas las demás respuestas mencionan. –
Lo haces exactamente de la misma manera que en C++. La inclusión de encabezado es una característica del preprocesador C. – avakar
Pero tienes todas esas funciones estáticas y funciones públicas, supongo que no es tan fácil. – Cartesius00