btb@ncoast.UUCP (Brad Banko) (03/14/88)
how does one use global data in C programming? i thought that you just create a header file containing the global data declarations and then #include it into each of your source files, but when i try this (using Mark Williams C on an Atari ST), I get a "symbol redefined" message from the linker. basically, the type of thing that I am trying to do is: x.h: int i,j; x.c: #include "x.h" xyz() { i = ... } y.c: #include "x.h" zzt() { i = j ... } K&R doesn't help me out... the stuff about externs and header files is sort of minimal. Thanks. -- Brad Banko Columbus, Ohio (formerly ...!decvax!cwruecmp!ncoast!btb) btb%ncoast@mandrill.cwru.edu "The only thing we have to fear on this planet is man." -- Carl Jung, 1875-1961
karl@haddock.ISC.COM (Karl Heuer) (03/18/88)
In article <7506@ncoast.UUCP> btb@ncoast.UUCP (Brad Banko) writes: >i thought that you just create a header file containing the global data >declarations and then #include it into each of your source files, but >when i try this (using Mark Williams C on an Atari ST), I get >a "symbol redefined" message from the linker. Yes. After the preprocessing phase is through, what you have is a set of source files each of which contains "int i, j;". Although this is accepted by some implementations, it is not portable. "extern int i, j;" is a declaration; "int i, j;" is a definition. Each object must have exactly one definition. The best$ way to do this is to change your header file to use the "extern" keyword, and pick one source file (or make a new one) to contain the definitions. Thus: x.h: extern int i, j; x.c: #include "x.h" xyz() { ... i = ... } extern.c: #include "x.h" int i, j; If you want them to be initialized to non-zero values, put the initializers in extern.c ("int i=3, j=4;"). (Actually, some implementations seem to require the initializers anyway, to distinguish a definition from a declaration; so you might want to add them even if they're zero.) Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint ________ $ Another popular style, which I do not recommend, is to have x.h contain "global int i, j;" where "global" is a macro defined with a null expansion in extern.c but expanding to "extern" for everyone else.
PEPRBV%CFAAMP.BITNET@husc6.harvard.EDU (Bob Babcock) (03/18/88)
>>how does one use global data in C programming?
Basically, the global variables should be declared with the extern
keyword in every source file but one. (Note that this is really
a linker requirement; I'm not sure whether all environments require
this.) The way I do this is in the include file, I put
EXTERN int x,y;
in main (before the file is included) I put
#define EXTERN
and in all other routines I put
#define EXTERN extern
If the global variable is explicitly initialized, you need to put in
#ifdef's of some sort so that the initialization is only done where the
extern keyword is absent.
nather@ut-sally.UUCP (Ed Nather) (03/18/88)
In article <3032@haddock.ISC.COM>, karl@haddock.ISC.COM (Karl Heuer) writes: > In article <7506@ncoast.UUCP> btb@ncoast.UUCP (Brad Banko) writes: > >i thought that you just create a header file containing the global data > >declarations and then #include it into each of your source files, but > >when i try this (using Mark Williams C on an Atari ST), I get > >a "symbol redefined" message from the linker. > > Yes. After the preprocessing phase is through, what you have is a set of > source files each of which contains "int i, j;". Although this is accepted by > some implementations, it is not portable. > > $ Another popular style, which I do not recommend, is to have x.h contain > "global int i, j;" where "global" is a macro defined with a null expansion in > extern.c but expanding to "extern" for everyone else. I find that this, too, has limitations, since pre-initialized definitions don't work. I finally solved the problem (to my satisfaction anyway) by writing a program I call "tglob" which takes the "master" set of global definitions, and turns it into a second file with "extern" inserted in the right places, and with definitions removed. It creates a file called "sglob" which can then be #included in all files except main(), which #includes the definitions. This way, if I change anything in the gloabl definition file, I needn't also remember to change it in the other file. I was ALWAYS making that mistake. I use "make" and include the dependency that re-creates "sglob" whenever the global definition file has been changed. I mailed a few copies of an earlier version that did not handle struct{} definitions properly, but didn't keep a list of customers. If anyone wants a copy of the program I'll mail it on request. I use it both under Unix and with the MSC and Turbo C compilers under MS-DOS. -- Ed Nather Astronomy Dept, U of Texas @ Austin {allegra,ihnp4}!{noao,ut-sally}!utastro!nather nather@astro.AS.UTEXAS.EDU
maart@cs.vu.nl (Maarten Litmaath) (03/18/88)
In article <7506@ncoast.UUCP> btb@ncoast.UUCP (Brad Banko) writes: \... \x.h: \ int i,j; \ \x.c: \#include "x.h" \ \xyz() { \ i = ... \} \ \y.c: \#include "x.h" \ \zzt() { \ i = j ... \} \... You have to reserve space for the variables only in one file, in the other files you must declare the variables "extern", so the following is a beautiful solution (thanks to Paul Polderman [polder@cs.vu.nl]): -------------------------------------------------------------------- global.h: #ifndef GLOBAL #define GLOBAL extern #endif GLOBAL GLOBAL int i, j; -------------------------------------------------------------------- global.c: #define GLOBAL #include "global.h" -------------------------------------------------------------------- x.c: #include "global.h" xyz() { i = ... } -------------------------------------------------------------------- y.c: #include "global.h" zzt() { i = j ... } -------------------------------------------------------------------- cc x.c y.c global.c -------------------------------------------------------------------- Regards. -- South-Africa: |Maarten Litmaath @ Free U Amsterdam: revival of the Third Reich |maart@cs.vu.nl, mcvax!botter!ark!maart
cox@bentley.UUCP (MH Cox) (03/19/88)
In article <10780@ut-sally.UUCP> nather@ut-sally.UUCP writes: >In article <3032@haddock.ISC.COM>, karl@haddock.ISC.COM (Karl Heuer) writes: >> In article <7506@ncoast.UUCP> btb@ncoast.UUCP (Brad Banko) writes: >> >i thought that you just create a header file containing the global data >> >declarations and then #include it into each of your source files, but >> >when i try this (using Mark Williams C on an Atari ST), I get >> >a "symbol redefined" message from the linker. >> >> Yes. After the preprocessing phase is through, what you have is a set of >> source files each of which contains "int i, j;". Although this is accepted by >> some implementations, it is not portable. >> >> $ Another popular style, which I do not recommend, is to have x.h contain >> "global int i, j;" where "global" is a macro defined with a null expansion in >> extern.c but expanding to "extern" for everyone else. > >I find that this, too, has limitations, since pre-initialized definitions don't >work. I finally solved the problem (to my satisfaction anyway) by writing a >program I call "tglob" which takes the "master" set of global definitions, >and turns it into a second file with "extern" inserted in the right places, >and with definitions removed. It creates a file called "sglob" which can >then be #included in all files except main(), which #includes the definitions. > >This way, if I change anything in the gloabl definition file, I needn't also >remember to change it in the other file. I was ALWAYS making that mistake. >I use "make" and include the dependency that re-creates "sglob" whenever the >global definition file has been changed. A better way (my opinion) would be to have one file, e.g. globals.c or in main.c, with all the initialized definitions. Then create a header file with all the "extern" declarations without the initializations. Include this in all your files, INCLUDING the globals.c or main.c. The{ compiler will then catch any errors of the type: globals.h: extern int an_extern_int; globals.c: long an_extern_int = 0; /* wrong type */ A second suggestion is to put all the extern global declarations be put into one header file. That makes it easy to "grep" all the files in the directory to determine which ones access global variables (the compiler should warn you about files that access global variables but don't include the header file). -- ========================================================================== Michael H. Cox ARPA: cox@garage.nj.att.com AT&T Bell Labs UUCP: ihnp4!bentley!cox 184 Liberty Corner Road COMPU$ERVE: 76525,3703 Rm 3N-D04 Warren, NJ 07060 (201) 580-8622 ==========================================================================
gwyn@brl-smoke.ARPA (Doug Gwyn ) (03/20/88)
In article <1089@bentley.UUCP> cox@bentley.UUCP (59463-MH Cox) writes: >A better way (my opinion) would be to have one file, e.g. globals.c or in >main.c, with all the initialized definitions. Source code that has a large number of global data pooled like this is woefully out of control. The proper place for defining a global datum (of which there should not be many!) is in the module that controls its meaning. If there isn't any such module, chances are that the design is quite poor.
djones@megatest.UUCP (Dave Jones) (03/22/88)
in article <12471@brl-adm.ARPA>, PEPRBV%CFAAMP.BITNET@husc6.harvard.EDU (Bob Babcock) says: > >>>how does one use global data in C programming? > > Basically, the global variables should be declared with the extern > keyword in every source file but one. (Note that this is really > a linker requirement; I'm not sure whether all environments require > this.) The way I do this is in the include file, I put > EXTERN int x,y; > in main (before the file is included) I put > #define EXTERN > and in all other routines I put > #define EXTERN extern > If the global variable is explicitly initialized, you need to put in > #ifdef's of some sort so that the initialization is only done where the > extern keyword is absent. Are you aware of the organization SLMA? I thought not. Before you spend another anguished night, please contact your local chapter of Silly Little Macros Anonymous. You owe it to yourself, to your code, and to generations of code-maintainers to come. It's only the first step, but a step you will never regret. This is something you should not have to face by yourself. One line at a time, Dave J.