Nuevo

Compilación de un programa en C









Compilación de un programa en C: - Detrás de escena


C es un lenguaje de alto nivel y necesita un compilador para convertirlo en un código ejecutable para que el programa pueda ejecutarse en nuestra máquina.

¿Cómo compilamos y ejecutamos un programa en C?

A continuación se detallan los pasos que utilizamos en una máquina Ubuntu con el compilador gcc.
  • 7Primero creamos un programa en C usando un editor y guardamos el archivo como filename.c
     $ vi filename.c
    El diagrama de la derecha muestra un programa simple para sumar dos números.
  • Luego compílelo usando el siguiente comando.
     $ gcc –Wall filename.c –o filename
    La opción -Wall habilita todos los mensajes de advertencia del compilador. Se recomienda esta opción para generar un mejor código. 
    La opción -o se usa para especificar el nombre del archivo de salida. Si no usamos esta opción, se genera un archivo de salida con el nombre a.out.
  • Después de que se genera el ejecutable de compilación y ejecutamos el ejecutable generado usando el siguiente comando.
     $ ./nombredearchivo 


¿Qué pasa dentro del proceso de compilación?

El compilador convierte un programa en C en un ejecutable.

Al ejecutar el siguiente comando, obtenemos todos los archivos intermedios en el directorio actual junto con el ejecutable.
 $ gcc –Wall –save-temps filename.c –o filename 
La siguiente captura de pantalla muestra todos los archivos intermedios generados.

Veamos uno por uno lo que contienen estos archivos intermedios.

Preprocesamiento

Esta es la primera fase a través de la cual se pasa el código fuente. Esta fase incluye:
  • Eliminación de comentarios
  • Expansión de macros
  • Expansión de los archivos incluidos.
  • Compilación condicional
La salida preprocesada se almacena en el nombre del archivo .i . Veamos qué hay dentro de filename.i: usando $ vi filename.i
En el resultado anterior, el archivo fuente está lleno de mucha información, pero al final nuestro código se conserva. 
Análisis:
  • printf contiene ahora a + b en lugar de agregar (a, b) porque las macros se han expandido.
  • Los comentarios se eliminan.
  • #include <stdio.h> falta, en su lugar vemos mucho código. Por lo tanto, los archivos de encabezado se han expandido e incluido en nuestro archivo fuente.

Compilando

El siguiente paso es compilar filename.i y producir un; archivo de salida compilado intermedio filename.s . Este archivo está en instrucciones de nivel de ensamblaje. Veamos a través de este archivo usando $ vi filename.s

La instantánea muestra que está en lenguaje ensamblador, que el ensamblador puede entender.

Montaje

En esta fase, el filename.s se toma como entrada y el ensamblador lo convierte en nombre de archivo . Este archivo contiene instrucciones a nivel de máquina. En esta fase, solo el código existente se convierte en lenguaje máquina, las llamadas a funciones como printf () no se resuelven. Veamos este archivo usando $ vi filename.o

Enlace

Esta es la fase final en la que se realizan todos los enlaces de llamadas a funciones con sus definiciones. Linker sabe dónde se implementan todas estas funciones. Linker también realiza un trabajo adicional, agrega un código adicional a nuestro programa que se requiere cuando el programa se inicia y finaliza. Por ejemplo, hay un código que se requiere para configurar el entorno, como pasar argumentos de línea de comandos. Esta tarea se puede verificar fácilmente usando $ size filename.o y $ size filename . A través de estos comandos, sabemos que el archivo de salida aumenta de un archivo objeto a un archivo ejecutable. Esto se debe al código adicional que el enlazador agrega con nuestro programa. Tenga en cuenta que GCC por defecto realiza enlaces dinámicos, por lo que printf () está vinculado dinámicamente en el programa anterior. 



No hay comentarios