Posterior a de nuestra prolongada selección de información solucionamos esta traba que tienen muchos de nuestros lectores. Te regalamos la solución y nuestro deseo es servirte de gran apoyo.
Solución:
Aquí están sucediendo algunas cosas diferentes. Primero, repasaré cómo funciona la compilación básica de varios archivos.
Si tiene varios archivos, lo importante es la diferencia entre la declaración y la definición de una función. La definición es probablemente a la que está acostumbrado cuando define funciones: escribe el contenido de la función, como
int square(int i)
return i*i;
La declaración, por otro lado, le permite declarar al compilador que sabe que existe una función, pero no le dice al compilador qué es. Por ejemplo, podrías escribir
int square(int i);
Y el compilador esperaría que la función “cuadrado” se defina en otro lugar.
Ahora, si tiene dos archivos diferentes que quiere interoperar (por ejemplo, digamos que la función “cuadrado” está definida en add.c, y quiere llamar a cuadrado (10) en main.c), necesita hacer ambos una definición y una declaración. Primero, define cuadrado en add.c. Entonces tú declarar al principio de main.c. Esto le permite al compilador saber cuando está compilando main.c que hay una función “cuadrado” que está definida en otra parte. Ahora, debe compilar main.cy add.c en archivos de objeto. Puedes hacer esto llamando
gcc -c main.c
gcc -c add.c
Esto producirá los archivos main.o y add.o. Contienen las funciones compiladas, pero no son del todo ejecutables. Lo importante que hay que entender aquí es que main.o es “incompleto” en cierto sentido. Al compilar main.o, le dijiste que la función “cuadrado” existe, pero la función “cuadrado” no está definida dentro de main.o. Así main.o tiene una especie de “referencia colgante” a la función “cuadrado”. No se compilará en un programa completo a menos que lo combine con otro archivo .o (o .so o .a) que contenga una definición de “cuadrado”. Si solo intentas Enlace main.o en un programa, es decir
gcc -o executable main.o
Obtendrá un error, porque el compilador intentará resolver la referencia colgante a la función “cuadrado”, pero no encontrará ninguna definición para ella. Sin embargo, si incluye add.o al vincular (vincular es el proceso de resolviendo todas estas referencias a funciones indefinidas al convertir archivos .o en ejecutables o archivos .so), entonces no habrá ningún problema. es decir
gcc -o executable main.o add.o
Así que así es como funcionalmente usar funciones en archivos C, pero estilísticamente, lo que acabo de mostrarles es “no es el camino correcto”. La única razón por la que lo hice es porque creo que te ayudará a entender mejor lo que está pasando, en lugar de depender de “#include magia”. Ahora, es posible que haya notado antes que las cosas se complican un poco si tiene que volver a declarar todas las funciones que desea usar en la parte superior de main.c Es por eso que a menudo los programas en C usan archivos auxiliares llamados “encabezados” que tienen una extensión .h . La idea de un encabezado es que contiene solo las declaraciones de las funciones, sin sus definiciones. De esta manera, para compilar un programa usando funciones definidas en add.c, no necesita declarar manualmente cada función que está usando, ni necesita #incluir todo el archivo add.c en su código. En su lugar, puede #include add.h, que simplemente contiene el declaraciones de todas las funciones de add.c.
Ahora, un repaso sobre #include: #include simplemente copia el contenido de un archivo directamente en otro. Entonces, por ejemplo, el código
abc
#include "wtf.txt"
def
es exactamente equivalente a
abc
hello world
def
asumiendo que wtf.txt contiene el texto “hola mundo”.
Entonces, si ponemos todas las declaraciones de add.c en add.h (es decir
int square(int i);
y luego en la parte superior de main.c, escribimos
#include "add.h"
Esto es funcionalmente lo mismo que si hubiéramos declarado manualmente la función “cuadrado” en la parte superior de main.c.
Entonces, la idea general de usar encabezados es que puede tener un archivo especial que declare automáticamente todas las funciones que necesita con solo # incluirlo.
Sin embargo, los encabezados también tienen un uso más común. Supongamos que main.c usa funciones de 50 archivos diferentes. La parte superior de main.c se vería así:
#include "add.h"
#include "divide.h"
#include "multiply.h"
#include "eat-pie.h"
...
En cambio, la gente a menudo mueve todos esos #includes al archivo de encabezado main.h, y solo #include main.h de main.c. En este caso, el archivo de encabezado sirve dos propósitos. Declara las funciones en main.c para su uso cuando se incluyen en otros archivos, y incluye todas las dependencias de main.c cuando se incluye desde main.c. Usarlo de esta manera también permite cadenas de dependencias. Si #incluye add.h, no solo obtiene las funciones definidas en add.c, sino que también obtiene implícitamente cualquier función que use add.c, y cualquier función ellos usar, y así sucesivamente.
Además, de manera más sutil, # incluir un archivo de encabezado de su propio archivo .c comprueba implícitamente los errores que comete. Si, por ejemplo, definió accidentalmente cuadrado como
double square(int i);
en add.h, normalmente es posible que no se dé cuenta hasta que haya vinculado que main.o está buscando uno definición de cuadrado, y add.o está proporcionando otro, incompatible uno. Esto hará que obtenga errores al vincular, por lo que no se dará cuenta del error hasta más adelante en el proceso de compilación. Sin embargo, si #incluye add.h de add.c, al compilador, su archivo se ve así
#include "add.h"
int square(int i)
return i*i;
que después de procesar la declaración #include se verá así
double square(int i);
int square(int i)
return i*i;
Lo que el compilador notará al compilar add.c, y le informará. Efectivamente, incluir su propio encabezado de esta manera evita que publicite falsamente en otros archivos el tipo de funciones que está proporcionando.
Por qué puede usar una función sin siquiera declararla
Como habrás notado, en algunos casos puedes usar una función sin que cada uno la declare o #incluya ningún archivo que la declare. Esto es estúpido y todos están de acuerdo en que esto es estúpido. Sin embargo, es una característica heredada del lenguaje de programación C (y los compiladores de C) que si usa una función sin declararla primero, simplemente asume que es una función que devuelve el tipo “int”. Entonces, en efecto, usar una función es declarar implícitamente esa función como una función que devuelve “int” si no está ya declarada. Es un comportamiento muy extraño si lo piensa, y el compilador debería advertirle si está haciendo ese comportamiento.
Guardias de cabecera
Otra práctica común es el uso de “Header Guards”. Para explicar los protectores de encabezado, veamos un posible problema. Digamos que tenemos dos archivos: herp.c y derp.c, y ellos ambos desea utilizar funciones contenidas en cada uno de los otros. Siguiendo las pautas anteriores, es posible que tenga un herp.h con la línea
#include "derp.h"
y un derp.h con la línea
#include "herp.h"
Ahora, si lo piensa, #include “derp.h” se convertirá al contenido de derp.h, que a su vez contiene la línea #include “herp.h”, que se convertirá al contenido de herp. mano ese contiene … y así sucesivamente, por lo que el compilador continuará por siempre expandiendo las inclusiones. De manera similar, si main.h # incluye tanto herp.h como derp.h, y tanto herp.h como derp.h incluyen add.h, vemos que en main.h, terminamos con dos copias de add.h, una como resultado de #incluyendo herp.h, y otra como resultado de incluir derp.h. Entonces, ¿la solución? Un “protector de encabezado”, es decir, un fragmento de código que evita que un encabezado se #incluya dos veces. Para add.h, por ejemplo, la forma normal de hacer esto es:
#ifndef ADD_H
#define ADD_H
int sqrt(int i);
...
#endif
Este fragmento de código esencialmente le dice al preprocesador (la parte del compilador que maneja todas las declaraciones “#XXX”) que verifique si “ADD_H” ya está definido. Si no lo es (sinortedef) luego primero define “ADD_H” (en este contexto, ADD_H no tiene que ser definido como cualquier cosa, es solo un booleano que está definido o no), y luego define el resto del contenido del encabezado. Sin embargo, si ADD_H ya está definido, entonces #incluir este archivo servirá nada, porque no hay nada fuera del bloque #ifndef. Entonces, la idea es que solo la primera vez que se incluya en un archivo dado, realmente agregará texto a ese archivo. Después de eso, # incluirlo no agregará ningún texto adicional a su archivo. ADD_H es solo un símbolo arbitrario que elige para realizar un seguimiento de si add.h ya se ha incluido. Para cada encabezado, utiliza un símbolo diferente para realizar un seguimiento de si se ha incluido o no. Por ejemplo, herp.h probablemente usaría HERP_H en lugar de ADD_H. El uso de un “protector de encabezado” solucionará cualquiera de los problemas que enumeré anteriormente, en los que se incluyen copias duplicadas de un archivo o un bucle infinito de #includes.
El problema es que no deberías estar #include
ing un archivo .c.
Para usar una función en otro archivo, debe declararla. Por lo general, cada archivo .c (excepto main.c) tiene un archivo de encabezado asociado (.h) que declara correctamente todas las funciones definidas en el archivo .c. Usted puede declarar tantas veces como desee (siempre que todas las declaraciones sean idénticas), pero solo puede haber una definición.
Que pasa cuando tu #include "add.c"
es que el texto de add.c está incluido en main.c, dando main.ca definición (y, como efecto secundario, una declaración) de add
. Luego, cuando compila add.c por sí mismo, eso crea otro definicion de add
. Por lo tanto, hay dos definiciones de la función y el compilador se asusta porque no sabe cuál usar.
Si lo cambia a #include "add.h"
, donde add.h se parece a esto:
#ifndef ADD_H
#define ADD_H
extern int add(int x, int y);
#endif /* ADD_H - Google "include guard" for more info about this trickery */
entonces main.c tiene una declaración de add
y puede usar la función, pero la definición de add
está bastante firme solo en el archivo add.c, por lo que solo existe una vez, por lo que se compilará correctamente.
Aquí hay un ejemplo simple de llamar a una función desde un programa c diferente
permítanme nombrar el programa principal como main.cy el programa que contiene la función como function.c para la función.c Estoy creando el archivo de encabezado llamado function.h
C Principal
#include"function.h"
int main()
int a = sum(1,2);
return a;
function.c
int function(int a,int b)
return a+b;
function.h
int function(int,int);
Para compilar use el comando que se indica a continuación
g ++ main.c function.c -o main
Aquí la explicación detallada. En el programa principal, he llamado a la función para sumar 2 números. Los valores 1 y 2 en el programa principal se alimentaron a la función en la función. C a través de la función de encabezado. H que contiene el punto de acceso o el puente a la función. c
Para obtener más detalles, puede consultar los enlaces que se proporcionan a continuación.
http://www.cplusplus.com/forum/beginner/34691/
https://social.msdn.microsoft.com/Forums/en-US/4ea70f43-a0d5-43f8-8e24-78e90f208110/calling-a-function-in-a-file-from-another-file?forum=winembplatdev
Agregue una declaración de impresión para verificar el resultado o use echo $? después de la ejecución del archivo principal
Reseñas y puntuaciones del post
Recuerda algo, que puedes permitirte valorar este ensayo si diste con la contestación.