Discussion:
Variables externas en programas en C
(demasiado antiguo para responder)
recurrente
2004-09-02 09:19:08 UTC
Permalink
Hola gente, ante todo quiero decir que no soy programador profesional ni
mucho menos, así que si estoy cometiendo alguna barbaridad inclino
humildemente mi cabeza..

Resulta que tengo un programa compuesto por muchos ficheros *.c y uno al que
llaman todos que es common.h, que tiene la estructura siguiente:

#IFDEF __MAIN
#DEFINE EXT ""
#ELSE
#DEFINE EXT extern
#endif
EXT int una_variable;
EXT float otra_variable;

de forma que al incluirla en el fichero main.c (que define la macro __MAIN)
se declaren como variables normales y en el resto de los ficheros como
variables externas. La cosa está claro en que son muchas variables y no
todas se usan en todos los ficheros fuente. ¿Es esto un desperdicio de
memoria o el compilador es lo bastante listo como para descartar las
variables no utilizadas al crear los *.o?


Gracias y un saludo,

Recurrente
--
Programa para generar la campaña política de George W. Bush

sed 's/comunis/terroris/g' Panfletos_50.txt > Panfletos_2K.txt
Jose Antonio
2004-09-02 13:27:03 UTC
Permalink
Post by recurrente
Hola gente, ante todo quiero decir que no soy programador profesional ni
mucho menos, así que si estoy cometiendo alguna barbaridad inclino
humildemente mi cabeza..
Resulta que tengo un programa compuesto por muchos ficheros *.c y uno al que
#IFDEF __MAIN
#DEFINE EXT ""
#ELSE
#DEFINE EXT extern
#endif
EXT int una_variable;
EXT float otra_variable;
Este truquillo creo haberlo visto en el código del Minix ;-)
Post by recurrente
de forma que al incluirla en el fichero main.c (que define la macro __MAIN)
se declaren como variables normales y en el resto de los ficheros como
variables externas. La cosa está claro en que son muchas variables y no
todas se usan en todos los ficheros fuente. ¿Es esto un desperdicio de
memoria o el compilador es lo bastante listo como para descartar las
variables no utilizadas al crear los *.o?
De memoria no, ninguna variable "publica" puede declararse 2 veces,
daría error de compilación, por eso se usa "extern" en todos los módulos
menos en uno, el main.

En el módulo main, que es donde se declara la variable de forma normal,
es donde el compilador reserva el espacio en memoria para dicha
variable. "extern" solo sirve para indicarle al compilador que la
variable es externa al módulo, por tanto no reserva sitio en memoria
para ella para aquellos módulos donde está declarada así.

Por otro lado, si se desperdicia una cosa, "símbolos". Al tener muchas
variables globales ya no podrás usar una variable que tenga el mismo
nombre y de lo contrario te dará un error de compilación.

Si vas a usar variables que sólo se tengan que ver en el mismo módulo,
decláralas como locales: dentro del fuente *.c (no la cabecera) y
anteponiendo "static".

Un saludo.

Jose.
Alberto Giménez
2004-09-02 11:10:39 UTC
Permalink
Post by recurrente
Resulta que tengo un programa compuesto por muchos ficheros *.c y uno al que
No lo llaman, lo incluyen *fisicamente* en sus contenidos antes de
realizar la compilación.
Post by recurrente
#IFDEF __MAIN
#DEFINE EXT ""
#ELSE
#DEFINE EXT extern
#endif
EXT int una_variable;
EXT float otra_variable;
Todo esto es innecesario. Necesitas leer acerca del significado de
extern y la diferencia entre declaración y definición.

Estas varlables que necesitas se tienen que definir (decirle al
compilador que reserve memoria para ellas) en un y solo un lugar
(imagino que en main.c), y fuera de *cualquier* función:

main.c:
int una_variable;
float otra_variable;

Esto son variables globales que están disponibles para cualquier fichero
que las necesite.

Desde otro fichero, digamos usavars.c, no tenemos que volver a *definir*
estas variables, porque main ya le ha dicho al compilador "oye,
reservame un int y un float pa mí". Esto es, "declaramos" las variables.

Lo que tiene que hacer usavars.c para usar estas variables globales es
decirle al compilador "oye, *alguien* ha reservado por ahi un par de
variables int y float. Déjame acceder a ellas, ya que son globales":

extern int una_variable;
extern float otra_variable;

Eso lo tendrías que hacer para cada fichero que las necesitara. ¿Manera
de ahorrarse esto? Crear una cabecera que lo haga por tí, e incluírla en
cada fichero fuente que necesite estas dos variables:

vars.h:
extern int una_variable;
extern float otra_variable;

main.c:
#include "vars.h"
^^^^^^^^^^^^^^^^ Esto aquí realmente no es necesario, ya que la
definición de las variables globales está en la misma unidad de
compilación, pero vamos, lo pongo aquí para que lo veas algo más claro.

usavars.c:
#include "vars.h"

Como ves, ese lío infernel de IFNDEFs no hace falta :)
Saludos
--
Luis Alberto Giménez
JabberID: ***@amessage.de
GnuPG ID: 0x3BAABDE1
Pascal Bourguignon
2004-09-02 20:01:19 UTC
Permalink
Post by Alberto Giménez
Post by recurrente
Resulta que tengo un programa compuesto por muchos ficheros *.c y uno al que
No lo llaman, lo incluyen *fisicamente* en sus contenidos antes de
realizar la compilación.
Post by recurrente
#IFDEF __MAIN
#DEFINE EXT ""
#ELSE
#DEFINE EXT extern
#endif
EXT int una_variable;
EXT float otra_variable;
Todo esto es innecesario. Necesitas leer acerca del significado de
extern y la diferencia entre declaración y definición.
Estas varlables que necesitas se tienen que definir (decirle al
compilador que reserve memoria para ellas) en un y solo un lugar
int una_variable;
float otra_variable;
Esto son variables globales que están disponibles para cualquier fichero
que las necesite.
Desde otro fichero, digamos usavars.c, no tenemos que volver a *definir*
estas variables, porque main ya le ha dicho al compilador "oye,
reservame un int y un float pa mí". Esto es, "declaramos" las variables.
Lo que tiene que hacer usavars.c para usar estas variables globales es
decirle al compilador "oye, *alguien* ha reservado por ahi un par de
extern int una_variable;
extern float otra_variable;
Eso lo tendrías que hacer para cada fichero que las necesitara. ¿Manera
de ahorrarse esto? Crear una cabecera que lo haga por tí, e incluírla en
extern int una_variable;
extern float otra_variable;
#include "vars.h"
^^^^^^^^^^^^^^^^ Esto aquí realmente no es necesario, ya que la
definición de las variables globales está en la misma unidad de
compilación, pero vamos, lo pongo aquí para que lo veas algo más claro.
#include "vars.h"
Como ves, ese lío infernel de IFNDEFs no hace falta :)
Por supuesto, no es preciso, pero facilita mucho la vida. Así, no hay
riesgo de error, de diferencia entre las variables definidas y las
declaradas.

Si lo haces como dices, puedes tener algo tal:

vars.h:
extern int una_var;
extern int otra_var;

main.c:
char una_var;
char otra_var;

y luego un bug guapo en usavars.c:

#include "vars.h"
void f(void){una_var=5550960;}

Sino,
* no sé que se puede escribir las directrices del pre-procesador
en mayusculas;

* "" int una_variable; es un error sintactico;

* Los nombres empezando con _ o __ estan reservados por el sistema o
el compilador;
Post by Alberto Giménez
Post by recurrente
#ifdef MAIN
#define EXT
#else
#define EXT extern
#endif
EXT int una_variable;
EXT float otra_variable;
Finalmente, lo mejor es no usar variables globales, y pasar el estado
por parametros. Sin pensarlo, se puede hacer esto:

main.h:

typedef struct {
int una_variable;
float otra_variable;
} globales_t;

main.c:
int main(int argc,char** argv){
globales_t* g=(globales_t*)malloc(sizeof(*g));
f1(g);
f2(g);
}

modulo.c:
#include "main.h"
void f1(globales_t* g){ g->una_variable=5550960; }


Por supuesto, si el programa trata de planetas, por ejemplo, mejor
llamar esta estructura por el nombre de la clase: planeta_t. Luego
podras tratas varios objetos planeta_t en el mismo programa.
--
__Pascal Bourguignon__ http://www.informatimago.com/

Our enemies are innovative and resourceful, and so are we. They never
stop thinking about new ways to harm our country and our people, and
neither do we.
recurrente
2004-09-03 10:55:41 UTC
Permalink
Post by Pascal Bourguignon
* no sé que se puede escribir las directrices del pre-procesador
en mayusculas;
* "" int una_variable; es un error sintactico;
* Los nombres empezando con _ o __ estan reservados por el sistema o
el compilador;
Ostras, pues sí, pero vamos, copié el código de memoria y he cometido todos
esos fallos (desde luego, podría trabajar haciendo espionaje
industrial :-D), pero en la versión original está bien (si no, el amigo gcc
ya me hubiera dicho algo).

Pues sí puede ser mejor lo que dices, tanto por claridad como por que da la
posibilidad de reutilizar partes del código más fácilmente.

Gracias

Recurrente
--
Programa para generar la campaña política de George W. Bush

sed 's/comun/terror/g' Panfletos_50.txt > Panfletos_2K.txt
Loading...