c include c-preprocessor code-organization project-organization

¿Incluyendo un archivo fuente C en otro?



include c-preprocessor (10)

¿está bien? sí, compilará

es recomendado? Los archivos no - .c se compilan en archivos .obj, que se vinculan entre sí después de la compilación (por el vinculador) en el ejecutable (o biblioteca), por lo que no es necesario incluir un archivo .c en otro. Lo que probablemente quiera hacer en su lugar es crear un archivo .h que liste las funciones / variables disponibles en el otro archivo .c e incluya el archivo .h

¿Está bien (o incluso recomendado / buena práctica) incluir #include .c archivo en otro archivo .c? ¿Qué sucede cuando están incluidos en un archivo de proyecto?


El lenguaje C no prohíbe ese tipo de #include, pero la unidad de traducción resultante todavía tiene que ser válida C.

No sé qué programa está usando con un archivo .prj. Si está usando algo como "make" o Visual Studio o lo que sea, solo asegúrese de configurar su lista de archivos para compilar sin la que no puede compilar de forma independiente.


Incluir un archivo C en otro archivo es legal, pero no es aconsejable, a menos que sepa exactamente por qué lo hace y qué intenta lograr.
Estoy casi seguro de que si publicas aquí la razón detrás de tu pregunta, la comunidad te encontrará otra forma más apropiada de lograr tu objetivo (ten en cuenta el "casi", ya que es posible que esta sea la solución dada el contexto )

Por cierto, me perdí la segunda parte de la pregunta. Si el archivo C se incluye en otro archivo y, al mismo tiempo, se incluye en el proyecto, probablemente terminará con un problema de símbolo duplicado por el que se vinculan los objetos, es decir, la misma función se definirá dos veces (a menos que sean estáticas).


La extensión del archivo no es importante para la mayoría de los compiladores de C, por lo que funcionará.

Sin embargo, dependiendo de su configuración de proyecto o archivo, el archivo c incluido podría generar un archivo de objeto separado. Al vincular eso, puede generar símbolos doblemente definidos.


No.

Dependiendo de su entorno de compilación (no especifique), puede encontrar que funciona exactamente de la manera que desea.

Sin embargo, hay muchos entornos (tanto IDEs como muchos Makefiles hechos a mano) que esperan compilar * .c: si eso sucede, probablemente termines con errores del enlazador debido a símbolos duplicados.

Como regla, esta práctica debe ser evitada.

Si debe #incluir el origen (y generalmente debe evitarse), use un sufijo de archivo diferente para el archivo.


Pensé que compartiría una situación en la que mi equipo decidió incluir archivos .c. Nuestra arquitectura consiste en gran parte en módulos que están desacoplados a través de un sistema de mensajes. Estos manejadores de mensajes son públicos y llaman a muchas funciones locales de trabajadores estáticos para hacer su trabajo. El problema surgió cuando intentamos obtener cobertura para nuestros casos de prueba unitaria, ya que la única forma de ejercer este código de implementación privada era indirectamente a través de la interfaz de mensajes públicos. Con algunas funciones de trabajador hasta la rodilla en la pila, esto resultó ser una pesadilla para lograr una cobertura adecuada.

La inclusión de los archivos .c nos dio una forma de llegar al engranaje en la máquina que estábamos interesados ​​en probar.


Puede incluir correctamente archivos .C o .CPP en otros archivos fuente. Dependiendo de su IDE, generalmente puede evitar la doble vinculación mirando las propiedades de los archivos fuente que desea incluir, generalmente haciendo clic derecho sobre ella y haciendo clic en Propiedades, y desmarcar / verificar compilar / vincular / excluir de compilación o cualquier otra opción tal vez. O no podría incluir el archivo en el proyecto en sí, por lo que el IDE ni siquiera sabrá que existe y no intentará compilarlo. Y con makefiles, simplemente no pondría el archivo en él para compilar y vincular.

EDITAR: Lo siento, lo hice una respuesta en lugar de una respuesta a otras respuestas :(


Puede usar el compilador gcc en Linux para vincular dos archivos c en una salida. Supongamos que tiene dos archivos c uno es ''main.c'' y otro es ''support.c''. Entonces el comando para unir estos dos es

gcc main.c support.c -o main.out

De esta forma, dos archivos se vincularán a una única salida main.out Para ejecutar la salida, el comando será

./main.out

Si está utilizando la función en main.c que se declara en el archivo support.c, debe declararla en main también utilizando la clase de almacenamiento extern.


Utilizado correctamente, esta puede ser una técnica útil.

Supongamos que tiene un subsistema complejo y crítico para el rendimiento con una interfaz pública bastante pequeña y una gran cantidad de códigos de implementación no reutilizables. El código se ejecuta en varios miles de líneas, un centenar de funciones privadas y bastante información privada. Si trabaja con sistemas incrustados no triviales, es probable que trate esta situación con la frecuencia suficiente.

Su solución probablemente será en capas, modular y desacoplada, y estos aspectos se pueden representar y reforzar útilmente codificando diferentes partes del subsistema en diferentes archivos.

Con C, puede perder mucho al hacer esto. Casi todas las cadenas de herramientas ofrecen una optimización decente para una sola unidad de compilación, pero son muy pesimistas sobre cualquier cosa declarada externamente.

Si pones todo en un módulo fuente C, obtienes -

  • Mejoras en el rendimiento y el tamaño del código: las llamadas a funciones se incluirán en muchos casos. Incluso sin incluir, el compilador tiene la oportunidad de producir un código más eficiente.

  • Datos de nivel de enlace y ocultación de funciones.

  • Evitar la contaminación del espacio de nombres y su corolario: puede usar nombres menos difíciles de manejar.

  • Compilación y vinculación más rápida.

Pero también tienes un desastre profano cuando se trata de editar este archivo y pierdes la modularidad implícita. Esto puede superarse dividiendo la fuente en varios archivos e incluyéndolos para producir una sola unidad de compilación.

Sin embargo, debe imponer algunas convenciones para administrar esto correctamente. Esto dependerá de su cadena de herramientas hasta cierto punto, pero algunos consejos generales son:

  • Coloque la interfaz pública en un archivo de encabezado separado; de todos modos, debería estar haciendo esto.

  • Tener un archivo .c principal que incluya todos los archivos .c subsidiarios. Esto también podría incluir el código para la interfaz pública.

  • Utilice guardias de compilación para asegurarse de que los encabezados privados y los módulos de origen no estén incluidos en las unidades de compilación externas.

  • Todos los datos y funciones privados deben declararse estáticos.

  • Mantener la distinción conceptual entre archivos .c y .h. Esto aprovecha las convenciones existentes. La diferencia es que tendrás muchas declaraciones estáticas en tus encabezados.

  • Si su cadena de herramientas no impone ninguna razón para no hacerlo, asigne un nombre a los archivos de implementación privados como .c y .h. Si usa incluir guardias, estos no producirán código y no introducirán nombres nuevos (puede terminar con algunos segmentos vacíos durante el enlace). La gran ventaja es que otras herramientas (por ejemplo, IDE) tratarán estos archivos de manera adecuada.


deberías agregar un encabezado como este

#include <another.c>

nota: ambos archivos deben colocarse en el mismo lugar