/
Inicio :: Foros

 F.A.Q.F.A.Q.                  Conéctese para revisar sus mensajesConéctese para revisar sus mensajes   

Diferencias entre funciones del preprocesador y enlazador

 
      Índice del Foro elrincondelc.com -> Principiantes C/C++
Ver tema anterior :: Ver siguiente tema  
AutorMensaje
virtualelrincon



Registrado: 30 Abr 2014
Mensajes: 9

MensajePublicado: 01/05/2014 9:53 am
Título: Diferencias entre funciones del preprocesador y enlazador

Hola, estoy muy confundido en cuanto a que hace cada uno. Tengo entendido que el preprocesador mediante la directiva #include por ejemplo incluye el contenido de una libreria externa en el codigo que será compilado. Luego el enlazador rellena los huecos que deja el compilador para las llamadas a las funciones de la biblioteca. Luego ambos procesos hacen lo mismo? Completan el código? no entiendo
Volver arriba
vangodp



Registrado: 25 Ene 2014
Mensajes: 30

MensajePublicado: 02/05/2014 12:36 am
Título:

a ver... como lo explico lo poco que se XDD
Cuando escribimos un codigo lo guardamos con .cpp o .c segun el lenguaje claro. Cuando lo compilamos ese antes de ser un exe hay otro proceso que es el de tranformar el archivo .cpp en un archivo objeto que termina con .o

O sea de archivo.cpp -> archivo.o
Si generas un código de un solo archivo no entenderás pero si ya has logrado hacer un código que incluya cabeceras tienes mas de un archivo. Por ejemplo puedes tener 2 archivos que se llamen main.cpp y otro que llama función.cpp que es otro archivo para guardar por ejemplo una función en el, el caso es irrelevante, lo que nos interesa para entender es tener claro que tenemos 2 archivos.
Entonces expliquemos un poco como va eso.

Un programa en c o cpp si ya lo sabes se desvía todo el rato. El programa funciona linea tras linea hasta que encuentra una función, la ves que la función no esta ahí pero con poner su nombre se invoca esa función¿no? O sea el programa lo que hace realmente no es nada de invocar con velas a los espiritus ni na parecido XDD, simplemente para la ejecución va hacia donde se encuentra la función aun que sea en otro archivo la ejecuta y vuelve al punto donde lo había dejado. Hasta aquí nada nuevo.
Digamos que la función que dije antes esta en el función.cpp, y que diga hola mundo solamente. En el archivo main.cpp esta la función principal main por eso lo llamo main.cpp nuestro main.cpp llama la función hola en función.cpp es una tontería lo que digo pero en programas complejos te vas a comer los mocos con puede que hasta cientos de archivos XDD ya veras XD
Bien mas o menos tenemos 2 archivos, vamos a compilar le damos al botón...Entra en acción el pre compilador haciendo lo que mencionas...sustituye todo lo que tiene # delante es su tarea, es como decir que todo el contenido de iostream (una libreria para escribir en pantalla cpp) se pegara en la linea #include<iostream>, eso realmente ya hace que se agrande el archivo. Lo mismo le pasa al funcion.cpp se va hacer su tarea de pre procesado.
Una vez terminado se crea los archivos binarios pero realmente son archivos independientes o sea "2" archivos binarios que son main.o y funcion.o.
como puede ser eso si solo tenemos un solo ejecutable como vamos a tener 2 objetos. Ahi es donde entra el enlazador, crea uno solo archivo antes de hacer el exe "pegando" y lo pongo entre por que realmente no pega nada simplemente pega la función en alguna parte del mismo archivo y pone en el lugar donde hacemos la llamada a la función un aviso diciendo en que parte de la memoria se encuentra. Si realmente pusiéramos inline antes de la función se pegaría literalmente la función en cada lugar donde la llamamos pero si la función no es inline pues eso es lo que hace, que cada vez que vea que la llamamos se desvía hacia donde esta la función y vuelve. Como puedes imaginar eso tiene un coste ya que se pierde tiempo cada vez que se desvía con inline seria mas rápido pero la diferencia es que solo tenemos una función, si usamos inline tendremos una función cada vez que la llamemos o sea una copia por cada llamada, si la vas a llamar uno o 2 veces a lo mejor te interesa hacerla inline que hace que tu programa sea mas rápido pero a cambio el ejecutable va ser mayor, eso lo puedes ver haciendo una función que diga hola mundo, pones el inline antes de declarar la función y si la llamas una vez y miras el tamaño del ejecutable, sera menor que si la llamas 10 o mas veces. Bueno eso ya no entra en la duda solo que es tarea del enlazador.
Como veras es un trozo de código igual que las librerias solo que no lleva el # delante para que lo identifique el precompilador, el enlazador enlaza todos esos desvíos en la linea de código. si lleva el # delante es fácil identificar por que le estamos decindo claramente que debe sustituir el #include<stdio> por el contenido de stdio de la librería, pero cada función también es un trozo de código y o se debe hacerse llamadas a ese trozo de código o hacerlas inline para que se copie en lugar donde se llama para que no pegue saltos a cambio de un código mas grande, eso lo decides tu (Mas rápido o mas pequeño, son las opciones que tiene)
Así que en esencia ¡¡¡¡si ambos hacen la misma tarea!!! rellenan los huecos que hacemos en el archivo XD.Como somos tan vaguillos pues vamos dejando agujeros por todas alas partes que para nuestra suerte tenemos esos 2 programillas majos que nos hace el trabajo sucio ^^
Como bien dice uno es pre o sea lo hace antes de compilar el otro hace una especie de enlace a las distintas partes del código cuando ese ya es un archivo objeto.
Mire esta foto: http://2.bp.blogspot.com/-8Q6IOiKYQ1s/UFs9fIee8fI/AAAAAAAAAzw/LE5aTDaHRYQ/s1600/compilacion.png

Si quieres saber mas busque en google "proceso de compilado cpp" y ya veras como funciona mas técnicamente. Mi versión es la del jardín ^^, hay explicaciones mas claras y mas complejas según como lo busques, ademas no se el nivel que tienes así que te deje la simples que es la que se jeje.
Suerte, espero no haberte llenado la cabeza con basura jeje
Volver arriba
virtualelrincon



Registrado: 30 Abr 2014
Mensajes: 9

MensajePublicado: 02/05/2014 8:14 am
Título:

Gracias por tu explicación, pero me quede super mareado. El dibujo si lo entendi, pero voy a seguir tu consejo de buscar un poco mas en google. Wink
Volver arriba
vangodp



Registrado: 25 Ene 2014
Mensajes: 30

MensajePublicado: 03/05/2014 5:44 am
Título:

esto hace el Precompilador por que le damos una orden con el #


Despues se compila:

Y obtenemos los archivos OBJETO o .o

uno por cada .c o cpp por que a los .cpp no haces includes solo haces includes de los headers.
Ahí es donde entra el enlazador.

En enlazador hace eso:


esta haciendo lo mismo que el pre compilador pero no con el archivo fuente sino con los binarios.

Por eso digo que hacen lo mismo pero de distintas formas.
Los headers se incrustan pero los .c/cpp se genera un objeto, y si son varios obj hay que unirlos.

Internamente el enlazador pega cada función en su lugar si es inline caso contrario envez de pegarlas deja un mensaje diciendo "¡¡La función que llamas esta en linea tal, ve allí y ejecuta la función!!". Después la función al terminar devuelve el control al programa principal main.

Normal


void decir(){
printf("Hola Mundo!!!");
}

main(){
decir();
decir();
decir();
}

Lo de arriba tiene ese efecto en el enlazador:

main(){
vaya a la funcion decir y la ejecuta;
vaya a la funcion decir y la ejecuta;
vaya a la funcion decir y la ejecuta;
}

con el inline:

inline void decir(){
printf("Hola Mundo!!!");
}

main(){
decir();
decir();
decir();
}

tiene ese efecto

main(){
se pega aquí todo el contenido de la función decir;
se pega aquí todo el contenido de la función decir;
se pega aquí todo el contenido de la función decir;
}


Creo que ya ves la diferencia

con inline se pega el código 3 veces, no parece malo verdad?
pero si la función tuviera cientos de lineas seria un disparate copiarlas varias veces.Si tuvieras muchas variables declaradas esas se duplicarían en memoria para cada llamada método inline.
Se gana en velocidad al no tener que saltar hacia donde esta la función pero a cambio la memoria se satura, prueba lo y lo veras a que cada llamada a una función inline crea una copia en el lugar donde la llamas y el exe sera mas grande.


Ya la forma normal "sin el inline" hace desvíos cada ves que encuentra una llamada.
Es como cuando no estas en casa y dejas una nota,"Estoy en la casa del vecino".No hay varias copias de ti mismo dentro de tu casa en cada habitación.

Ya no se que decirte si no lo entiendes jeje
Lo siento es todo lo que se, a ver si alguien ayuda mejor.
Volver arriba
virtualelrincon



Registrado: 30 Abr 2014
Mensajes: 9

MensajePublicado: 03/05/2014 8:26 am
Título:

vangodp la verdad con semejante explicación me da verguenza decir que no entiendo, pero voy a explicar lo que entiendo así capaz se me entiende mejor. Yo tengo entendido que el enlazador une el archivo objeto que ha sido compilado a otros archivos objetos llamados librerias (realmente no se si copia parte de las librerias o todo el archivo de donde se encuentra la funcion). Eso por una parte, por otra parte el preprocesador, hace cambios en el texto de nuestro código fuente como quitar los comentarios pero además mediante la directiva #include (y aca es donde me mareo) incluye todo el archivo de cabecera o parte de el (no se) en el archivo fuente para que el compilador pueda compilar las funciones. La confusión viene en que no se porque tanto el preprocesador como el enlazador incluyen partes de archivo o archivos completos en nuestro archivo para que las funciones funcionen. ¿Ambos hacen lo mismo?
Volver arriba
vangodp



Registrado: 25 Ene 2014
Mensajes: 30

MensajePublicado: 03/05/2014 3:33 pm
Título:

Pero ni siempre en eso archivos header están las funciones... Puede que solo estén las declaraciones y los .cpp ya estén incluso compilados.

Por ejemplo yo tengo 3 archivos, uno es el main.cpp el otro lo llamo no se...funcion.h "h de header" y luego otro llamado funcion.cpp

En el main ni que decir que estará el programa principal main().
Luego en el funcion.h solo pongo el prototipo o la declaración de una clase por ejemplo, luego la implementación las pongo en el funcion.cpp

Imagine que en main aya esto:

Código:
#include <iostream>
#include "funcion.h"
using namespace std;

int main(){
    mifuncion();
    return 0;
}


luego en el funcion.h tengo:
Código:
void mifuncion();


Y luego en el funcion.cpp:
Código:
#include <iostream> //siempre que usemos cout debemos incluirla antes.

void mifuncion(){
    std::cout << "Aqui estoy =D"<<std::endl;
}



Si te fías bien que es lo que te ha incluido el precompilador en main??¡¡Nada!!!Simplemente el prototipo, la función no esta ahí sino en funcion.cpp, no hiciste el include a funcion.cpp sino a funcion.h.
Claro que para que funcione debes crear un proyecto en codeblocks

Si no te lo incluyo el precompilador quien crees que lo aya echo?¡Tu amigo el enlazador!! XDD Y lo hizo cuando ese ya era un binario por que esa tarea se la realiza en los archivos ya siendo binarios.
O sea que el que te da una librería te puede dar incluso partes de código precompiladas y solo la declaración en el header, por eso hacen casi lo mismo pero de distintas formas.
Ojo con eso una cosa es la declaración y otra es la la implementación. Claro que todo el código puede estar en el header pero no tiene por que ser eso siempre así.
De echo seguro vas a ver la declaración en el header y la implementación el los .cpp mas veces que el contrario.
¿Que necesita una función para funcionar? pues que esta se cree antes ¿no? ¡Si! Pero... puedes poner un prototipo ¿no?Una declaración de una clase es como una especie de prototipo por eso suele estar en la cabecera por que en ella esta la declaración, luego la función va en otra parte para mantener el código mas limpio y fácil de encontrar, algo por el tema de divides y vencerás Wink

Si tienes dudas sigue preguntando pero creo que ya con eso XDD

Ahi esta el por que...puede que el archivo este troceado en partes y que algunas las incluyas en el preprocesador y otras te lo haga el amigo enlazador que las conecta todas para crear la aplicación.

si no quieres crear un proyecto hace un include de la funcion.cpp en cualquier parte del main y veras funcionando igual, lo que pasa es que codeblocks tiene una opción que te compila los archivos que marques sin que tengas necesidad de hacer los includes. yo agrego los .h que son las declaraciones y luego digo que codeblocks compile los .cpp por mi pero puedes hacer la inclusion de los cpp.
Eso todo lo vas a entender mejor cuando entres en el tema de clases.

No te compliques tanto la vida, tómalo como una religión y acéptalo.
Un conductor no tiene que saber como trabaja el motor del coche para poder conducirlo, si sabes como funciona sus mecanismos de embrague freno y acelerador estas capacitado a conducir, ya lo de fabricar el motor o repararlo es cosa de mecánicos y como conductor que eres no te va a llevar a ninguna parte saber cuantos tornillos lleva el motor o el tamaño del cilindro del coche XDDD

Suerte Wink
Volver arriba
virtualelrincon



Registrado: 30 Abr 2014
Mensajes: 9

MensajePublicado: 10/05/2014 10:13 am
Título:

Creo que para poder entender el tema y la respuesta voy a tener que terminar de estudiar C y después estudiar C++. Pero de vez en cuando a medida que avance me pegare una visita por aquí. Gracias vangodp!
Volver arriba
      Índice del Foro elrincondelc.com -> Principiantes C/C++
Página 1 de 1Todas las horas están en GMT - 8 Horas

 
No puede crear mensajes
No puede responder temas
No puede editar sus mensajes
No puede borrar sus mensajes
No puede votar en encuestas

(c) ElRincondelC.com

Un proyecto de UrlanHeat.com