[comp.lang.c] Extern variables question

hascall@atanasoff.cs.iastate.edu (John Hascall) (11/16/89)

    I have been involved in a ``discussion'' over which (if any) of the
four following pairs of modules are identical in result.  Assume that in
each case the two modules are compiled separately and linked with:

     int main(int argc, char **argv) {
        void foo(void); void bar(void); foo(); bar(); return(1); }


          module1.c             module2.c
          -------------------   -------------------
   (a)    int i;                int i;
          void foo(void) {}     void bar(void) {}

   (b)    extern int i;         int i;
          void foo(void) {}     void bar(void) {}

   (c)    extern int i;         int i = 0;
          void foo(void) {}     void bar(void) {}

   (d)    extern int i;         extern int i;
          void foo(void) {}     void bar(void) {}

What is the answer and WHY?

Thanks, John 

CMH117@PSUVM.BITNET (Charles Hannum) (11/16/89)

You should define a global variable in *exactly one* module, no more, no less.
All other modules should refer to it as an extern.  Most linkers will generate
an error if a global variable by the same name is defined in more than one
module.

As for initializing it, that depends ...  Your answer could be either B or C.

macphee@engcon.marshall.ltv.com (SCMACPHEE) (11/16/89)

If I understand the question correctly, you are trying to find out how
the int variable "i" will be scoped at link time.  I ran aross a similar
problem using VAX 'C', and it caused me a lot of heart-ache.  It appears
that when declaring outside of a function, 'C' defaults the type to 
extern.  To avoid the default extern type, declare it as static.

Hope this helped!

Scott
engcon!macphee@uunet.uu.net
LTV Missiles & Electronics Group, Dallas, Texas!

dan@charyb.COM (Dan Mick) (11/18/89)

In article <89320.012957CMH117@PSUVM.BITNET> CMH117@PSUVM.BITNET (Charles Hannum) writes:
>You should define a global variable in *exactly one* module, no more, no less.
>All other modules should refer to it as an extern.  Most linkers will generate
>an error if a global variable by the same name is defined in more than one
>module.

Again:  What?

Most PC linkers I've used will; but not Microsoft's, at least not with C 
5.1, and *no* Unix linker I've ever heard of does.  That seems, to me, to
be one of the huge implementation-philosophy differences between Unix-oid
C and PC-oid C.
-- 
.sig files are idiotic and wasteful.

will@charyb.COM (Will Crowder) (11/18/89)

In article <312@charyb.COM> dan@charyb.UUCP (Dan Mick) writes:

>In article <89320.012957CMH117@PSUVM.BITNET> CMH117@PSUVM.BITNET (Charles Hannum) writes:
>>
>>[comment about defining global data in only one module, and declaring
>> it in the other modules used]
>
>Again:  What?
>
>Most PC linkers I've used will; but not Microsoft's, at least not with C 
>5.1, and *no* Unix linker I've ever heard of does.  That seems, to me, to
>be one of the huge implementation-philosophy differences between Unix-oid
>C and PC-oid C.
>-- 
>.sig files are idiotic and wasteful.

Why the "What?", Dan?  The man's answer was good advice as far as I'm
concerned.  I prefer the PC-oid style.  It just seems to make sense that 
since you're defining storage for one location, you define it in one place.  
You can declare its existence wherever you want to use it.  This actually 
seems useful to me, since that way you can know that once you've found the 
definition of the variable you aren't using, you can remove it *in once 
place* and it's gone.  Other modules which used it will get complaints.  
Further, the PC-oid style encourages the concept of an object module 
"owning" a data object.  If indeed it is not appropriate for any single 
executable code module to own the data object, because it's used equally 
everywhere, then you can have a "global data" module which only defines 
the global data.  Again, the scope and ownership of the data object
is defined in the source module.

Also, the PC-oid style encourages (read: requires) differentiation between 
the definition of an object (which reserves space), and the declaration 
of an object (which does not).  I consider this useful: one object,
one definition, multiple declarations of its existence in other source
modules which use it, and might depend on its proper initialization,
and which will cause complaints if the object doesn't exist at linktime.

Will

walter@hpclwjm.HP.COM (Walter Murray) (11/18/89)

John Hascall writes:

>     I have been involved in a ``discussion'' over which (if any) of the
> four following pairs of modules are identical in result.  Assume that in
> each case the two modules are compiled separately and linked with:

>      int main(int argc, char **argv) {
>         void foo(void); void bar(void); foo(); bar(); return(1); }


>           module1.c             module2.c
>           -------------------   -------------------
>    (a)    int i;                int i;
>           void foo(void) {}     void bar(void) {}
> 
>    (b)    extern int i;         int i;
>           void foo(void) {}     void bar(void) {}
> 
>    (c)    extern int i;         int i = 0;
>           void foo(void) {}     void bar(void) {}
> 
>    (d)    extern int i;         extern int i;
>           void foo(void) {}     void bar(void) {}

> What is the answer and WHY?

This is something that varies depending on your compiler and linker.
In ANSI C, the answer is that all four cases are legal and produce
the same result.

> WHY?

Why not?  No rule has been violated.

The answer would be different if 'i' were actually used somewhere (other
than as part of the operand of sizeof).  Then case (a) would be illegal
(more than one "external definition" for 'i'), and case (d) would be
illegal (no "external definition" for 'i').  Cases (b) and (c) would
still be legal and have the same result.  Note that a global
declaration of the form "int i;" is called a tentative definition
and has the same effect as "int i = 0;" if it is the only declaration
for 'i' in that translation unit (module).

This whole area was a major standardization issue, and the rules
finally adopted by ANSI C try to accommodate as many existing
environments and implementations as possible.

Walter Murray
----------

tanner@cdis-1.uucp (Dr. T. Andrews) (11/20/89)

In article <316@charyb.COM>, will@charyb.COM (Will Crowder) writes:
) Further, the PC-oid style ...
The "pc-oid" style (occasionally called "ref/def" for references and
definition) pre-dates the IBM-PC.  The "unix-oid" (also known as
"common") style of course also pre-dates the IBM-PC.

The term "common" is meant in the fortran sense, rather than "usual".
-- 
Mulroney: "Cut trains.  Drive in | {bpa,uunet}!cdin-1!cdis-1!tanner
Canada.  We need the acid rain." | {attctc gatech!uflorida}!ki4pv!cdis-1!tanner