On 2012-10-03, lipska the kat <> wrote:
> Hi
>
> I have the following program
> distributed over 4 files
>
> /* foo.h */
> int foo;
This is an external *definition* and not merely a declaration, so you have
screwed up. As soon as this file is included in more than one translation unit,
foo becomes multiply defined. You want:
extern int foo;
This is purely a declaration now because of two features: the presence of the
extern, and the lack of an initializer. Now you need a definition of foo
somewhere.
Pick a source file where foo is going to reside, and and put an "int foo;"
there. Also, a good idea is to ensure that this source file includes
the header. If you ever change the type of foo, you get type checking
between the declaration in the header and the definition in that file.
> void fooset(int f);
Note that no "extern" is needed on function declaration, because declarations
without bodies are only declarations and not definitions. You can use extern
if you want:
extern void fooset(int f);
Putting extern on function declarations could help you remember to add it to
object declarations.
> int fooget(void);
> void fooinc(void);
>
> /* main.c */
> #include <stdio.h>
> #include <foo.h>
It's a poor idea to use angle brackets on your own header file.
And in fact, in many environments it will not work. You must have passed some
option to your compiler to make it work.
Header files are searched for in two places. Double quotes like #include
"foo.h" specify that one place is searched, and if the header is not found
there, then the other place is searched. Angle brackets indicate that
only the second place is searched.
In many common environments, the first place that is searched is the
same directory which contains the source file which is invoking the #include.
And the second place (used by the angle brackets include, or as
fallback for single quotes) is a bunch of system and compiler header file
directories, outside of the program.
So #include <foo.h> won't work unless you tell the compiler that your
project directory is one of the system directories. That's a bad idea
because then if someone makes a header which clashes with the name of
some system header, that header may get mistakenly included.
> Anyway, the question is who 'owns' the foo declared in foo.h
> Storage is obviously set aside as when I run the program I get the
> expected output
Why it works is that your environment implements the "Relaxed Ref/Def model"
of C linkage. That is to say, it allows multiple external definitions
for an object. These external definitions are merged into a single definition
during linkage.
You are being allowed to get away with a programming error which, in a "Strict
Ref/Def:" linkage model will not allow your program to link.
It is sharp of you to raise a question mark about this, and wonder
"who owns foo". Good for you!
For more information about "Relaxed Ref/Def" and "Strict Ref/Def", find
a document called "Rationale for the ANSI C Programming Language".
This is covered in section 3.1.2.2 of that document.
http://www.lysator.liu.se/c/rat/title.html
This was written by the committee back in the late 1980's when they
standarized the first C programming language.