Ver Mensaje Individual
  #3 (permalink)  
Antiguo 14/07/2003, 18:31
leonardop
 
Fecha de Ingreso: julio-2003
Mensajes: 165
Antigüedad: 21 años, 8 meses
Puntos: 1
Hola. Nuestro amigo josemi tiene razón en parte respecto al uso de variables extern. Básicamente, si tienes una variable que quieres compartir entre varios archivos .c, puedes definirla en algún archivo de ellos (generalmente aquel que contenga la función main()), y luego declarar esa misma variable usando la palabra clave extern en todos los demás archivos que usen esa variable.

Ahora bien, me parece a mí que te refieres a un tipo de situaciones sutilmente distintas. Tienes un archivo de cabeceras (.h) en donde tienes todo tipo de maravillas que usarás en varios archivos distintos (pueden ser prototipos, declaración de variables, enumeraciones, estructuras, etc.).

Si no te entiendo mal, tu curiosidad te ha llevado a hacerte la (muy buena) pregunta, ¿cómo hace el compilador para no redefinir las cosas si las incluye más de una vez? ¿tendré que hacer las inclusiones en un orden especial? Bueno, al menos esas preguntas me asaltaron a mí hace algún tiempo.

En ese caso, te cuento que hay un truco muy popular, y que muy posiblemente ya hayas visto en la práctica si has tenido la oportunidad de estudiar el código fuente de alguna aplicación seria. Incluso tengo entendido que herramientas de generación de código como las que vienen con el compilador de C++ de microsoft las implementan de forma natural.

El truco es simple: al comienzo del archivo de cabecera, digamos por ejemplo que tenemos uno que se llame maravillas.h, se coloca algo similar a esto:

Código:
#ifndef __MARAVILLAS_H
#define __MARAVILLAS_H
Después de estas líneas viene todo el contenido normal de tu archivo. Finalmente, justo después de tus últimas líneas de código, se cierra la directiva #ifndef:

Código:
#endif  /* __MARAVILLAS_H */
¿Ves cómo funciona el truco? Es simple y astuto, a decir verdad. El compilador tomará tus archivos de código fuente (sin importar el orden) y va incluyendo los archivos de cabecera en la medida en que se necesiten. En este ejemplo, la primera vez que maravillas.h sea incluido, la directiva #ifndef revisará si se ha definido previamente una macro con el nombre __MARAVILLAS_H, y por supuesto no la encentrará (a menos que la hayas definido en otra parte, por supuesto... por eso suele utilizarse la convención de usar el nombre del archivo con "underlines" al comienzo como nombre de la macro), así que ejecuta el código que encuentra a continuación, que de entrada empieza por definir la macro que acaba de revisar.

De este modo, en futuras inclusiones del archivo, la directiva #ifndef toma un rumbo diferente (ignorando el contenido del archivo). Como el final de la directiva condicional está al final del archivo, lo que se logra en la práctica es proteger el contenido completo del archivo para que no sea incluido y procesado más de una vez.

También es curioso que menciones esto como una duda sobre gcc. De hecho, este tipo de prácticas es tan común (o estándar, dicen los libros), que el pre-procesador de gcc lo reconoce y nisiquiera trata de acceder aquellos archivos que definen su "símbolo de protección". Realmente útil. Es muy bonito trabajar con gcc.

Un cordial saludo.