Disponible la nueva versión "donationware" 7.3 de OrganiZATOR
Descubre un nuevo concepto en el manejo de la información.
La mejor ayuda para sobrevivir en la moderna jungla de datos la tienes aquí.

Curso C++

[Home]  [Inicio]  [Índice]


1.4.2  Compilación

§1  Sinopsis

Hemos señalado ( 1.4) que estrictamente hablando, compilación se refiere al proceso de generación de código que sigue al preprocesado. Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintáctico, traduciéndolos en código de la máquina para la que compila.

El resultado de la compilación es un fichero objeto .OBJ, que contiene código máquina; directivas de enlazado; referencias externas; nombres de funciones, y datos generados a partir de los ficheros-fuente.

§2  Unidad de compilación

El trabajo del "compilador" se efectúa sobre un fichero denominado unidad de compilación ("Translation unit") o módulo. Se refiere a un fichero de código fuente (.c / .cpp) al que se añaden los ficheros #include, al que se suprimen las líneas correspondientes a las directivas de preprocesado. Es decir,  lo que resulta de pasar el fuente por el preprocesador.

El concepto de unidad de compilación es fundamental en C++ y en el resto de lenguajes que siguen procesos de construcción similares para sus ejecutables. E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duración de los objetos. Sintácticamente una unidad de compilación se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicación sobre este tipo de listas en: 1.3.1a).

Unidad de compilación:

Declaración externa

Declaración externa   Unidad de compilación

Declaración externa:

Definición de función

Declaración


El resultado de compilar la unidad de compilación es un fichero objeto (.obj / .o). Por lo general, en los proyectos de software se utilizan varias unidades de compilación que son compiladas separadamente para después enlazarlas en uno o varios ejecutables. Si como ocurre con frecuencia en proyectos grandes, la funcionalidad incluida en estas unidades de compilación debe ser reutilizada muchas veces, entonces no permanecen como tales ficheros .obj independientes, sino que se agrupan en librerías.

§3  Deformación de nombres

Cuando el compilador C++ traduce un módulo en el que existen funciones, los identificadores originales son cambiados por una versión distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la función. Esta distorsión o deformación de nombres, conocida también como decoración o planchado de nombres ("Name mangling"), es la que hace posible la sobrecarga de funciones ( 4.4.1a).  Puesto que aunque dos funciones compartan el mismo nombre, si son distintos los tipos de argumentos, las versiones internas ("planchadas") de tales nombres son distintas.

Nota: la razón de la "decoración" de nombres es de tipo histórico.  Las primeras implementaciones de C++ eran simplemente preprocesadores que traducían a C; después se compilaba en este lenguaje. Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el número y tipo de sus argumentos), cosa que no es posible en C, se recurrió a deformar los nombres de las funciones, asignándoles un nombre interno (para el compilador) que deriva de su nombre en el fuente agregándole datos sobre el número y tipo de los argumentos. Se consigue así que el compilador pueda distinguir las diversas versiones de una función sobrecargada.

Además de esto, la decoración de nombres es un mecanismo C++ de seguridad (de comprobación de tipos), que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros módulos son correctas (respecto a la idoneidad de los argumentos utilizados). Por ejemplo, en MS VC++, la función

void Func(int i);

se transforma internamente en  ?Func@@YAXH@Z

Hay que tener en cuenta que esta "decoración" de los nombres de las funciones no está especificada por el Estándar C++, de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo, MS VC++ y Borland C++ Builder no lo hacen igual). El resultado es que, salvo que se tomen precauciones especiales (que veremos a continuación), no está garantizado que las librerías construidas con un compilador C++ funcionen con otro.

§3.1 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsión en el fichero que se compila. Por ejemplo, cuando un módulo C++ se compila para ser enlazado con otros módulos (de compiladores o lenguajes distintos) en los que no se utiliza este "planchado" (o se realiza de forma distinta). Esto ocurre en especial cuando tales módulos deben ser enlazados con otros compilados en C (que no utiliza esta técnica).

Para evitar el "planchado", se utiliza la declaración extern "C" en la declaración (prototipo) de la función. Esta declaración puede realizarse a título individual o para un grupo (bloque de enlazado E1.4.4). Por ejemplo:

extern "C" void Cfunc(int);   // para una función


extern "C" {                  // para un bloque de enlazado
  void Cfunc1(int);
  void Cfunc2(int);
  void Cfunc3(int);
};

 

extern "C" {                  // para todas las de un fichero de cabecera
  #include "locallib.h"
};


Todas estas formas indican al compilador que las correspondientes funcione no deben ser "planchadas".

Nota: naturalmente lo anterior tiene un coste, representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el módulo en el que se evita la decoración de nombres.


§3.2
  Más sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 4.1.8d).

§3.3  La declaración: extern “C” no puede usarse con identificadores de clases ( 4.11.2a).

§3.4  No confundir la declaración extern "C" con la especificación de forma de llamada C ( 4.4.6a).

  Inicio.


[1]  Nótese que la palabra externo/a tiene varias connotaciones en C++. En este caso, se refiere a declaraciones hechas fuera de cualquier función; que por tanto, son globales al fichero  (enlazado externo tiene un sentido distinto).