[comp.lang.c] Correct or Not or Old-fashioned or Bug

zhoumi@nff.ncl.omron.co.jp (Zhou Mi) (05/20/91)

When I am working in a project, I find that someone in my group write
the following program. Though it seems work well, I still wonder if it
is correct or better ??

-----file 1 (named pro_all.h) ---------
	int i;

------file 2 (named pro_main.c) --------
	#include "pro_all.h"
	
	void main()
	{
		sub1();
		sub2();
		sub3();
	}
	
--------- file 3 (named pro_sub1.c) --------
	#include "pro_all.h"
	void sub1()
	{
		i = 1;
	}

--------- file 4 (named pro_sub2.c) ---------
	#include "pro_all.h"
	void sub2()
	{
		i++;
	}

--------- file 5 (named pro_sub3.c) ---------
        #include "pro_all.h"
        void sub3()
        {
		i += 3;
	}

	If anyone has the result, please mail to me.

	my E-mail address is:
			zhoumi@nff.ncl.omron.co.jp
--
+------
 From:   Zhou  Mi

 ||=======||{}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{}
 ||\    / ||{} Zhou Mi, RZE, Systems R&D LAB., OMRON Co.                    {}
 || \  /  ||{} E-mail:   zhoumi@nff.ncl.omron.co.jp                         {}
 ||  \/   ||{} TEL:  075-951-5111  x   3176                                 {}
 ||  /\   ||{}=============================================================={}
 || /     ||{} What is AI ? This is the very question that AI machine can   {}
 ||/      ||{} answer, but one can not !!                                   {}
 ||=======||{}______________________________________________________________{}

mikegord@generic.UUCP (Mike Gorodnitzky) (05/21/91)

There seems to be one problem that may prevent compiling, or rather, linking.

The problem is that because the variable 'i' is declared in several modules (4),the linker will choke as it is illegal to do this.  It will have global's called'i' conflicting with each other.  This is bad.

What you may want to do is declare in:

pro_all.h---------

     extern int  i;

pro_main.c--------

     int  i;


And keep the rest as is.  I haven't actually tried this, so can't be 100% sure about it, but it should work ok.

harry@spitws111.uk.sun.com (Harry Protoolis) (05/21/91)

In article <ZHOUMI.91May20182038@marlboro.nff.ncl.omron.co.jp>, zhoumi@nff.ncl.omron.co.jp (Zhou Mi) writes:
|> 
|> When I am working in a project, I find that someone in my group write
|> the following program. Though it seems work well, I still wonder if it
|> is correct or better ??
|> 
|> -----file 1 (named pro_all.h) ---------
|> 	int i;
|> more stuff where this is included into many .c files and used ...

This is not correct, you do not say what machine/OS you are using, but on
many systems (most ?) this practice would generate a linker error (multiple
definition of symbol i).

Maybe a standard lawyer out there can tell me what ANSI says on this one.

Anyway, if it is intended that i be a global variable it should be declared in
the interface file (.h) as 'extern int i', and defined in one of the .c files
as int i. This will generate one instance of the variable (in the 
implementation (.c) file containing the definition), which will be shared by
the whole program (i.e a global variable).

In general .h files should only contain declarations (i.e things like
typedef and extern). 'int i' is a definition and therefore belongs in
an implementation file (.c).

I am suprised it works at all and it is certainly not portable, or good style.

What machine/OS/Compiler are you using ????

Hope this helps,
Harry

-- 
'When I give food to the poor they call me a saint.
 When I ask why the poor have no food they call me a communist.'
         - Dom Helder Camara

grogers@convex.com (Geoffrey Rogers) (05/21/91)

In article <ZHOUMI.91May20182038@marlboro.nff.ncl.omron.co.jp> zhoumi@nff.ncl.omron.co.jp (Zhou Mi) writes:
>
>When I am working in a project, I find that someone in my group write
>the following program. Though it seems work well, I still wonder if it
>is correct or better ??
>
>-----file 1 (named pro_all.h) ---------
>	int i;
>
>------file 2 (named pro_main.c) --------
>	#include "pro_all.h"
>	
>	void main()
>	{
>		sub1();
>		sub2();
>		sub3();
>	}
>	
>--------- file 3 (named pro_sub1.c) --------
>	#include "pro_all.h"
>	void sub1()
>	{
>		i = 1;
>	}
>

In non-ANSI C compiler/loader environments this may or may not work. You
could get multiple defined symbols for i, depending upon the model that the
compiler used for external variables.

The above code in not ANSI conforming, because you do have multiple
definitions of i.

One of the ways that I got around this problem of only having one file
with all of my externals is to do the following:

-------------- file 1 (pro_all.h) ----------------------
#ifndef EXTERN
#define EXTERN	extern
#endif

EXTERN int i;

------------- file 2 (pro_main.c) ----------------------
#define EXTERN

#include "pro_all.h"

void main()
{
	sub1();
	sub2();
	sub3();
}

--------- file 3 (pro_sub1.c) --------
#include "pro_all.h"
void sub1()
{
	i = 1;
}

This way when pro_all.h is included in the main all the externals get
defined and when it gets included in other files they get declared.

+------------------------------------+---------------------------------+
| Geoffrey C. Rogers   		     | "Whose brain did you get?"      |
| grogers@convex.com                 | "Abbie Normal!"                 |
| {sun,uunet,uiucdcs}!convex!grogers |                                 |
+------------------------------------+---------------------------------+

grimlok@hubcap.clemson.edu (Mike Percy) (05/22/91)

grogers@convex.com (Geoffrey Rogers) writes:

>In article <ZHOUMI.91May20182038@marlboro.nff.ncl.omron.co.jp> zhoumi@nff.ncl.omron.co.jp (Zhou Mi) writes:
>>
>One of the ways that I got around this problem of only having one file
>with all of my externals is to do the following:

>-------------- file 1 (pro_all.h) ----------------------
>#ifndef EXTERN
>#define EXTERN	extern
>#endif

>EXTERN int i;

>------------- file 2 (pro_main.c) ----------------------
>#define EXTERN

>#include "pro_all.h"

>void main()
>{
>	sub1();
>	sub2();
>	sub3();
>}

>--------- file 3 (pro_sub1.c) --------
>#include "pro_all.h"
>void sub1()
>{
>	i = 1;
>}

I've seen people do this kind of thing a lot, but I've never liked
having to remeber to put #define EXTERN or some such in my code.  I've
found it easiest to confine my global data to two files:
globals.h
  extern int foo;
  extern double bar;  
  /* and so on, declaring all global variables */
 
and
globals.c
  int foo;
  double bar;
  /* rest of the definitions */

Since I've started doing this, I've not had any problems related to
global data.  One problem is on certain segmented machines, in certain
compilers memory models, I take a hit because of the segment
placement.

Comments?

"I don't know about your brain, but mine is really...bossy."
Mike Percy                    grimlok@hubcap.clemson.edu
ISD, Clemson University       mspercy@clemson.BITNET
(803)656-3780                 mspercy@clemson.clemson.edu

mccrady@torolab6.vnet.ibm.com ("++Don;") (05/22/91)

> From: grimlok@hubcap.clemson.edu (Mike Percy)
>
>                                               ... I've never liked
> having to remeber to put #define EXTERN or some such in my code.  I've
> found it easiest to confine my global data to two files:
> globals.h
>   extern int foo;
>   extern double bar;
>   /* and so on, declaring all global variables */
>
> and
> globals.c
>   int foo;
>   double bar;
>   /* rest of the definitions */
>
> Since I've started doing this, I've not had any problems related to
> global data.  One problem is on certain segmented machines, in certain
> compilers memory models, I take a hit because of the segment
> placement.
>
> Comments?

Splitting the declarations off from the definitions of variables
introduced the possibility of nasty pitfalls, where somebody decides
to change the type in the .h file, and forgets to change it in
the .c file.  Example:

     ----- globals.h ------------
       extern int    foo;
       extern double bar;
     ----------------------------

     ------ globals.c -----------
       short foo;
       float bar;
     ----------------------------

Some linkers won't catch this, and any stores into foo or bar
will probably whomp some other data.  I prefer the EXTERN approach
which you seem to dread, because it lets you DEFINE and DECLARE
objects at the same time.

     ------ globals.h -----------
        #ifdef MAIN
          #define EXTERN
          #define INIT(x)    = x
        #else
          #define EXTERN extern
          #define INIT(x)
        #endif

        EXTERN int foo    INIT(5);
        EXTERN double bar INIT(3.14);
     ----------------------------

     ------ globals.c -----------
       #define MAIN
       #include "globals.h"
     ----------------------------

++Don;

mjf@mjm.mjm.com (Mark Fresolone) (05/22/91)

> grimlok@hubcap.clemson.edu (Mike Percy) 
>grogers@convex.com (Geoffrey Rogers) writes:
>>In article <ZHOUMI.91May20182038@marlboro.nff.ncl.omron.co.jp> zhoumi@nff.ncl.omron.co.jp (Zhou Mi) writes:
>>>
>>One of the ways that I got around this problem of only having one file
>>with all of my externals is to do the following:
>>-------------- file 1 (pro_all.h) ----------------------
>>#ifndef EXTERN
>>#define EXTERN	extern
>>#endif
>>EXTERN int i;
>>------------- file 2 (pro_main.c) ----------------------
>>#define EXTERN
[...]
>I've seen people do this kind of thing a lot, but I've never liked
>having to remeber to put #define EXTERN or some such in my code.  I've
>found it easiest to confine my global data to two files:
>globals.h
>  extern int foo;
[..] >and
>globals.c
>  int foo;
[...]
>Comments?

I guess I use a hybrid of the two methods for public library data:
------ libName.h ------
#ifdef LIBName
int	foo = FOO_DEFAULT;
double	bar;
#else	/* LIBName */
extern int	foo;
extern double	bar;
#endif /* else LIBName */
------ libNameinit.c -------
#define LIBName
#include <libName.h>
...
------ appication.c --------
#include <libName.h>
....

This allows me initialization (see FOO_DEFAULT above) which would be
awkward in the first method, and good maintainability, since the data
is defined and declared in the same file.

Mark Fresolone					 mjf@mjm.com, rutgers!mjm!mjf
Melillo Consulting/MJM Software			908-873-0620/Fax 908-873-2250

enag@ifi.uio.no (Erik Naggum) (05/22/91)

"++Don;" (please use full names) writes:
|
|   > From: grimlok@hubcap.clemson.edu (Mike Percy)
|   ...
|   > globals.h
|   >   extern int foo;
|   >   extern double bar;
|   >   /* and so on, declaring all global variables */
|   ...
|   > globals.c
|   >   int foo;
|   >   double bar;
|   >   /* rest of the definitions */
|   >
|
|   Splitting the declarations off from the definitions of variables
|   introduced the possibility of nasty pitfalls, where somebody decides
|   to change the type in the .h file, and forgets to change it in
|   the .c file.  Example:

Good point.  What I've done a lot is like this

	-- globals.h --
	extern int foo;
	extern long bar;

	-- globals.c --
	#include "globals.h"

	int foo;
	long bar;

This lets the compiler check the types so the pitfall isn't any more.

One system I delivered was later "maintained" by a PC-based humanoid
with no clear idea of what he did to my code, and I was later hired to
do fire-fighting for them (sigh).  That "programmer" invented the
brilliant

	-- globals.c --
	#define extern /* */

	#include "globals.h"

I DO NOT recommend this, although it works on some compilers.

</Erik>
--
Erik Naggum             Professional Programmer            +47-2-836-863
Naggum Software             Electronic Text             <ERIK@NAGGUM.NO>
0118 OSLO, NORWAY       Computer Communications        <enag@ifi.uio.no>

volpe@camelback.crd.ge.com (Christopher R Volpe) (05/22/91)

In article <1991May21.150735.12200@convex.com>, grogers@convex.com
(Geoffrey Rogers) writes:
|>In non-ANSI C compiler/loader environments this may or may not work. You
|>could get multiple defined symbols for i, depending upon the model that the
|>compiler used for external variables.
|>
|>The above code in not ANSI conforming, because you do have multiple
|>definitions of i.

I think so far I have seen about 3 or 4 wrong answers to this question, such
as the above. There is nothing wrong with the referenced code as far as
the Standard is concerned. There are not multiple definitions of i, because
none of those *tentative* definitions has an initializer. In such a
situation, all tentative definitions are treated as a single definition
with initializer 0. (See A10.2 in K&R2 for an explanation)

-Chris

|>+------------------------------------+---------------------------------+
|>| Geoffrey C. Rogers   		     | "Whose brain did you get?"      |
|>| grogers@convex.com                 | "Abbie Normal!"                 |
|>| {sun,uunet,uiucdcs}!convex!grogers |                                 |
|>+------------------------------------+---------------------------------+
                                                                       
==================
Chris Volpe
G.E. Corporate R&D
volpecr@crd.ge.com

grimlok@hubcap.clemson.edu (Mike Percy) (05/22/91)

enag@ifi.uio.no (Erik Naggum) writes:

>"++Don;" (please use full names) writes:
>|   > From: grimlok@hubcap.clemson.edu (Mike Percy)
>|   Splitting the declarations off from the definitions of variables
>|   introduced the possibility of nasty pitfalls, where somebody decides
>|   to change the type in the .h file, and forgets to change it in
>|   the .c file.  Example:

>Good point.  What I've done a lot is like this

>	-- globals.h --
>	extern int foo;
>	extern long bar;

>	-- globals.c --
>	#include "globals.h"
>	int foo;
>	long bar;
 
Oops.  In my haste I left this out...of course I always #include
globals.h in globals.c.  Bad things can happen otherwise.  And of course
in the makefile
globals.obj : globals.c globals.h
(or the equivalent with implicit rules, or better yet using automatic
dependency checking).

>This lets the compiler check the types so the pitfall isn't any more.

>One system I delivered was later "maintained" by a PC-based humanoid
>with no clear idea of what he did to my code, and I was later hired to
>do fire-fighting for them (sigh).  That "programmer" invented the
>brilliant

>	-- globals.c --
>	#define extern /* */
>	#include "globals.h"

 
Blech.  I mean saving keystrokes is nice, but really!  I usually end up
writing globals.h, copy to globals.c, and globally change to get rid of
the externs:  <ESC>1,$s/extern//

"I don't know about your brain, but mine is really...bossy."
Mike Percy                    grimlok@hubcap.clemson.edu
ISD, Clemson University       mspercy@clemson.BITNET
(803)656-3780                 mspercy@clemson.clemson.edu
 

zhoumi@nff.ncl.omron.co.jp (Zhou Mi) (05/23/91)

	Up to now, I've got many answers. Here, I give my thanks to all the
people who gives me the answer by E-mail or by News.

	But, there are so many conflicting answers that I feel really 
confusion. Can anyone give me a proper conclusion or answer ??

	First all, I give my working environment here:
        I'm working on :
                machine: OMRON HOLONIC WORKSTATION SX9100/DT
                OS:     UNIOS-B 4.3BSD UNIX: 1.60Beta
                Compiler: both cc and gcc

	There are some of the answers , which I've get, as follows:

1)
Date: Mon, 20 May 91 09:02:17 PDT
From: raymond@math.berkeley.edu (Raymond Chen)
Message-Id: <9105201602.AA07902@math.berkeley.edu>
Received: by sunkist.berkeley.edu (4.1/1.31)
        id AA03310; Mon, 20 May 91 09:02:16 PDT
To: zhoumi@nff.ncl.omron (Zhou Mi)
Subject: Re: Correct or Not or Old-fashioned or Bug
Newsgroups: comp.lang.c
In-Reply-To: <ZHOUMI.91May20182038@marlboro.nff.ncl.omron.co.jp>
Organization: U.C. Berkeley
Status: RO

Although it is incorrect(even by the old K&R standard), it works on
unix (and only on unix) systems because of a bug in the linker.

From raymond@math.berkeley.edu Wed May 22 03:18:37 1991
Received: by othello.nff.ncl.omron.co.jp (5.65-omron/6.3J-omron)
        id AA06141; Wed, 22 May 91 03:18:31 +0900
Received: from math.Berkeley.EDU by uunet.uu.net with SMTP
        (5.61/UUNET-uucp-primary) id AA01257; Tue, 21 May 91 11:06:58 -0400
Received: from sunkist.berkeley.edu by math.berkeley.edu (4.1/1.33(math))
        id AA13916; Tue, 21 May 91 08:06:38 PDT
Date: Tue, 21 May 91 08:06:38 PDT
From: raymond@math.berkeley.edu (Raymond Chen)
Message-Id: <9105211506.AA13916@math.berkeley.edu>
To: zhoumi@nff.ncl.omron
Subject: Re: Correct or Not or Old-fashioned or Bug
Status: RO

|Why is the BUG still alive ??

Because the BUG is a hack used by the compiler/linker to control
whether or not to link stdio and/or floating point.

2)
Date: Tue, 21 May 91 15:05:55 GMT
From: steve@taumet.com (Stephen Clamage)
X-Local-Time: Tue, 21 May 91 08:05:55 PDT
To: zhoumi@nff.ncl.omron
Subject: Re: Correct or Not or Old-fashioned or Bug
Newsgroups: comp.lang.c
References: <ZHOUMI.91May20182038@marlboro.nff.ncl.omron.co.jp>
Status: RO

In comp.lang.c you write:

>When I am working in a project, I find that someone in my group write
>the following program. Though it seems work well, I still wonder if it
>is correct or better ??

[ 'int i;' included in all modules ]

Most Unix systems allow a declaration like
        int i;
to appear in more than one module.

Other systems require exactly one defining instance.  Technically,
        int i;
is a defining instance, while
        extern int i;
is not.

To be portable, the header file should contain
        extern int i;
and one module should contain
        int i;
(It is ok to have both
        extern int i;
        int i;
in the same module.)  This will compile and link correctly on all systems.

To avoid the problem of having to write declarations twice, here is a
trick that is often used:  Each header file looks like this:
        #ifndef EXTERN
        #define EXTERN extern
        #endif
        EXTERN int i;
        EXTERN double d;
        EXTERN struct foo bar;
        ...

Then when you include any header, all the variables are declared like this:
        extern int i;
        extern double d;
        extern struct foo bar;
In one module, such as the one including 'main()', you do this:
        #define EXTERN
        #include "file1.h"
        #include "file2.h"
        ...
Here 'EXTERN' is defined to be nothing, so the declarations now look
like this:
        int i;
        double d;
        struct foo bar;
You have a single source declaration for each variable, and exactly one
defining instance in the entire program for each.
--

Steve Clamage, TauMetric Corp, steve@taumet.com

Date: Wed, 22 May 91 8:01:36 PDT
From: Stephen D. Clamage <steve@taumet.com>
In-Reply-To: <9105220040.AA06573@marlboro.nff.ncl.omron.co.jp>; from "Zhou Mi" a
t May 22, 91 9:40 am
X-Mailer: ELM [version 2.3 PL2]
Message-Id: <9105220801.AA17473@taumet.com>
Status: RO

>       But why ---
> >> Most Unix systems allow a declaration like
> >>        int i;
> >> to appear in more than one module.
>               ??

This is called the "common" model, from the FORTRAN style of global
variables.  In FORTRAN, you didn't have global variables, but you
did have named sections of memory, called COMMON blocks.  Every module
(in original FORTRAN, every subroutine was its own module) which
referenced a COMMON block carried a declaration for it.  There was
no notion of a "defining instance" of a COMMON block, so the linker
had to take all these named blocks and allocate them to the same
address.

Early Unix C compilers used the same principle.  Each declaration of
a global data object was given the "common" attribute, and the
linker would allocate all global data items with the same name to the
same address.  This worked even if some were initialized.  Some linkers
would complain if more than one was initialized, and some would not;
in the latter case, you could not necessarily predict which initial
value would be used.

In some environments, the linker does not support common data, or
cannot reconcile an initialized item with a common item having the
same name.  So the most portable thing is not to use declarations
which result in objects with the "common" attribute.

--

Steve Clamage, TauMetric Corp, steve@taumet.com

3)
From: volpe@camelback.crd.ge.com (Christopher R Volpe)
Newsgroups: comp.lang.c
Subject: Re: Correct or Not or Old-fashioned or Bug
Date: 22 May 91 15:43:21 GMT
Reply-To: volpe@camelback.crd.ge.com (Christopher R Volpe)
Distribution: comp.lang.c

In article <1991May21.150735.12200@convex.com>, grogers@convex.com
(Geoffrey Rogers) writes:
|>In non-ANSI C compiler/loader environments this may or may not work. You
|>could get multiple defined symbols for i, depending upon the model that the
|>compiler used for external variables.
|>
|>The above code in not ANSI conforming, because you do have multiple
|>definitions of i.

I think so far I have seen about 3 or 4 wrong answers to this question, such
as the above. There is nothing wrong with the referenced code as far as
the Standard is concerned. There are not multiple definitions of i, because
none of those *tentative* definitions has an initializer. In such a
situation, all tentative definitions are treated as a single definition
with initializer 0. (See A10.2 in K&R2 for an explanation)

-Chris

|>+------------------------------------+---------------------------------+
|>| Geoffrey C. Rogers                       | "Whose brain did you get?"      |
|>| grogers@convex.com                 | "Abbie Normal!"                 |
|>| {sun,uunet,uiucdcs}!convex!grogers |                                 |
|>+------------------------------------+---------------------------------+

==================
Chris Volpe
G.E. Corporate R&D
volpecr@crd.ge.com

**********************************************************************
	My brain is going to CORE DUMP because of lacking of memory.

	Thanks again for all the answers.

--
+------
 From:   Zhou  Mi

 ||=======||{}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{}
 ||\    / ||{} Zhou Mi, RZE, Systems R&D LAB., OMRON Co.                    {}
 || \  /  ||{} E-mail:   zhoumi@nff.ncl.omron.co.jp                         {}
 ||  \/   ||{} TEL:  075-951-5111  x   3176                                 {}
 ||  /\   ||{}=============================================================={}
 || /     ||{} What is AI ? This is the very question that AI machine can   {}
 ||/      ||{} answer, but one can not !!                                   {}
 ||=======||{}______________________________________________________________{}

rjc@cstr.ed.ac.uk (Richard Caley) (05/24/91)

In article <ZHOUMI.91May23102519@marlboro.nff.ncl.omron.co.jp>, Zhou Mi (zm) writes:

zm> But, there are so many conflicting answers that I feel really 
zm> confusion. Can anyone give me a proper conclusion or answer ??

Me too, so I caved in and asked for divine guidence.

From K&R, K&R-II and Plaughter and Brodie...

The Old testament, the book of Reference, chapter 11, verse 2:

      ``The apearence of the extern keyword in an external
	definition indicates that storage for the identifiers being
	declared will be allocated in another file. Thus in a
	multi-file program, an external data definition without the
	extern specifier must appear in exactly one of the files.''

The New Testament, the book of Reference, chapter 10, verse 2:

      ``An external object declaration that does not have an
	initialiser, and does not contain the extern specifier, is a
	tentative definition. [...] If no definition for the object
	appears _in_the_translation_unit_, all its tentative
	definitions become a single definition with initialiser 0.''
		[emphasis mine].

The Commentaries:

      ``If a data object declaration is a tentative definition and you
	write no definition for the same object later in the
	translation unit, then the translater allocates storage for
	the data object at the end of the translation unit.''

Someone else will have to do the Tablets of Stone. 

TNT adds a comment that the multi-file version of the rule is
recognised by the standard as a common extension. 

--
rjc@cstr.ed.ac.uk	It was news to me too, too long on Unix.

scjones@thor.sdrc.com (Larry Jones) (05/24/91)

In article <19804@crdgw1.crd.ge.com>, volpe@camelback.crd.ge.com (Christopher R Volpe) writes:
> I think so far I have seen about 3 or 4 wrong answers to this question, such
> as the above. There is nothing wrong with the referenced code as far as
> the Standard is concerned. There are not multiple definitions of i, because
> none of those *tentative* definitions has an initializer. In such a
> situation, all tentative definitions are treated as a single definition
> with initializer 0. (See A10.2 in K&R2 for an explanation)

Not so.  WITHIN A SINGLE SOURCE FILE, multiple tentative definitions
are treated as a single definition, but the cited example had them
scattered across multiple files.  In this case, each file would end
up with a definition and the linker is justified in complaining about
it.
----
Larry Jones, SDRC, 2000 Eastman Dr., Milford, OH  45150-2789  513-576-2070
Domain: scjones@sdrc.com             Path: uunet!sdrc!scjones
I won't eat any cereal that doesn't turn the milk purple. -- Calvin

volpe@camelback.crd.ge.com (Christopher R Volpe) (05/29/91)

In article <164@thor.sdrc.com>, scjones@thor.sdrc.com (Larry Jones) writes:
|>Not so.  WITHIN A SINGLE SOURCE FILE, multiple tentative definitions
|>are treated as a single definition, but the cited example had them
|>scattered across multiple files.  In this case, each file would end
|>up with a definition and the linker is justified in complaining about
|>it.

Oops. Thanks. The small print on page 227 of K&R2 says that the behavior
I described is a common extension under Unix, but not Standard behavior.

|>----
|>Larry Jones, SDRC, 2000 Eastman Dr., Milford, OH  45150-2789  513-576-2070
|>Domain: scjones@sdrc.com             Path: uunet!sdrc!scjones
|>I won't eat any cereal that doesn't turn the milk purple. -- Calvin
                 
==================
Chris Volpe
G.E. Corporate R&D
volpecr@crd.ge.com