El compilador de C


El compilador de C

Este apartado es suficiente para dominar el uso básico del compilador de lenguaje C, a través del programa cc. Para comprender este texto no tienen por qué estar familiarizados con el C, aunque se precisan unas mínimas nociones de este lenguaje. Además, deberían conocer conceptos básicos relacionados con el desarrollo de programas, como programa fuente, objeto, enlace (linking), etc.

El programa cc. Pasos de compilación

Para compilar programas escritos en C, disponen de un compilador de nombre cc. Este compilador toma como parámetros los ficheros fuentes de que consta el programa final y, tras una serie de pasos, produce un fichero ejecutable. Si durante la compilación se produce un error, no se genera el ejecutable.

Los pasos de compilación en UNIX son al menos estos tres:

* Preproceso (macros, inclusión de ficheros...)

* Compilación a objeto

* Enlace (linking) de objetos y bibliotecas

El preproceso interpreta las macros creadas con #define y expande los ficheros para incluir con #include. No es de mucho interés para ustedes.

Un fichero una vez preprocesado se compila a código máquina, pero no se genera un ejecutable, sino un fichero objeto. Este estadio intermedio es necesario por muchos motivos, entre ellos que las rutinas de biblioteca, como printf, tienen que ser "empotradas" posteriormente para generar un ejecutable, y en general debido a que un programa en C puede constar de varios ficheros compilados por separado.

Por eso existe un último paso, denominado enlace (linking en inglés), en el cual se recogen todos los ficheros objetos más las bibliotecas (que también residen en ficheros) necesarios para producir el fichero ejecutable.

Convenciones en los nombres de ficheros

Como se ha visto, en el transcurso de la ejecución del cc aparecen en escena varias clases de ficheros: fuentes, objetos, bibliotecas, ejecutables... El compilador de C es capaz de distinguir la clase de un fichero en base a sus últimos caracteres. La siguiente tabla muestra las convenciones más habituales.
.c

fichero fuente en C
.h

fichero cabecera fuente en C (sólo útil para los #include)
.s

fichero fuente en ensamblador (también reconocido)
.i

fichero fuente tras ser preprocesado (raramente empleado por el usuario)
.o

fichero objeto
.a

fichero de biblioteca
El compilador de C sólo genera un ejecutable, de nombre a.out, aunque se le puede indicar que tenga otro nombre con la opción -onombre_de_ejecutable.

Uso del compilador

El programa cc se invoca desde el shell, admitiendo como argumentos los ficheros empleados para construir el ejecutable más una serie de opciones de compilación. Las opciones y modalidades de uso del cc son amplísimas, por lo que en esta guía nos limitaremos a exponer las más comunes y útiles.

Por omisión, el cc genera un ejecutable llamado a.out. En la línea de órdenes pueden incluir tanto ficheros fuentes en C como ficheros objeto, incluso fuentes en ensamblador[1]. Los nombres de los ficheros pueden aparecer en cualquier orden.

En el siguiente apartado aparece un resumen de opciones; antes de ello daremos algunos ejemplos.

Ejemplo 1:

cc pepe.c

Si pepe.c es un fichero fuente en C, se compila y se enlaza con las bibliotecas del sistema. Si no había errores sintácticos ni referencias a funciones o variables inexistentes, se genera el ejecutable a.out.

Ejemplo 2:

cc -o pepe main.c utilidades.c pepe.o -lm

Éste es un ejemplo más complejo donde anticipamos el uso de un par de opciones de compilación. La opción -o pepe sirve para que, en lugar de generar el fichero ejecutable pepe, en lugar de a.out. Para construir el ejecutable se hace uso explícito de cuatro elementos:

* Un fuente main.c (quizás con el programa principal)

* Otro fuente, utilidades.c (quizás con funciones adicionales)

* Un objeto pepe.o (tal vez con otras utilidades ya compiladas)

* La biblioteca matemática estándar (con la opción -lm)

Con este ejemplo hacemos ver que un programa en C puede estar compuesto de varios módulos en forma de ficheros fuentes. Y que si un módulo ya está compilado, podemos pasar como argumento al compilador el correspondiente .o para ahorrar tiempo.

Resumen de opciones para el compilador

Como ya se dijo, existe una infinidad de opciones para controlar la ejecución del cc. Algunas de las opciones más necesarias o comprensibles para ustedes son las siguientes:

-Aa

compila en C ANSI
-Ac
compila en C de K&R
-c
sólo compila, no hace el montaje
-Idirectorio
define directorios para buscar los #includes
-llib
monta la biblioteca lib
-Ldirectorio
define directorios para buscar las bibliotecas
-o fichero
establece el nombre del ejecutable
-O
optimiza el código
-On
optimiza el código hasta el nivel n
-S
genera un fuente .s en ensamblador; no compila
-v
modo locuaz: imprime todos los pasos

Las opciones del compilador de C pueden variar según la versión de UNIX que se utilice.

Laboratorio de operativos: El compilador de C está preparado para compilar en modo ANSI, con lo que no hace falta que escriban la opción -Aa.

Algunas bibliotecas útiles, para la opción -llib, son:

c

biblioteca estándar del C. No hace falta incluirla explícitamente
m
biblioteca estándar matemática
termcap
contiene rutinas de manejo de terminales
curses
contiene rutinas de visualización con ventanas, etc.
l
biblioteca para uso del lex y el yacc

El compilador de C++

Es muy probable que en la máquina en la que trabajen exista un compilador de C++. Describiremos brevemente las características de uno de los compiladores de C++ más difundidos, el de la casa GNU (software de distribución gratuita).

El compilador de la GNU se llama gcc, aunque se le puede invocar como gcc o c++. Es capaz de reconocer tanto fuentes en C como en C++. El gcc reconoce como fuentes en C++ a los ficheros con extensión .cxx o .C (letra "C" mayúscula).

Las opciones admitidas por el gcc son más o menos las mismas que acepta el compilador convencional de UNIX; aunque siempre es recomendable consultar el manual en línea.

[ ] 1 De hecho el paso de compilación a objeto suele atravesar una fase intermedia en que se genera un fichero en lenguaje ensamblador y se invoca al programa ensamblador del sistema.