Longfellow said:
After further review:
Longfellow wrote:
What I've done is declare a struct in a header file, which is included
in the files for both ends. For example:
Declaring structs, typedefs, function prototypes etc yes, defining
objects and function no.
-------
/* --- data.h --- */
struct data {
char question[80];
char answer[80];
} calc[80];
-------
Here you are not merely defining the struct, you are also defining an
object called calc which is an array of structs.
Not defining, just initializing.
No, it is NOT initialising, it is defining.
> This declaration is made only once in
the header file and not again referenced in the code.
It IS a definition of calc.
> It is assumed
that every file that has that header included should know what it needs
to know about that array of structs.
That is true, and that is the reason for providing an extern declaration.
Prohibition is against declaring an object more than once, I think.
It is, and by including the above header in more than one translation
unit that is *exactly* what you are doing.
> H&S
says on page 79 that one of the two exceptions to this rule is when an
object is declared as the same type every time, as in a header file that
can be shared with all code files.
You can declare an object (with the same time, or an incomplete
declaration that is compatible) as often as you want, but that is NOT
what the header does, the header defines the object.
> You are correct that an inclusion of
the header file in each code file is a duplicate declaration,
No, it is a definition, not a declaration.
> but this
exception exists because otherwise the standard C library would be
illegal.
No, because the standard headers declares, they do not define.
Note that for functions you don't need the extern keyword to provide
declarations (but you can), but with object types you do.
You want something like:
/* --- data.h --- */
#define CALC_SIZE 80
struct data {
char question[80];
char answer[80];
};
extern struct data calc[CALC_SIZE];
This does not compile.
It compiles perfectly when I try it. Have you put it through a compiler
and what error do you get?
Then, in EXACTLY one C source file (not header) which includes data.h
you have
struct data calc[CALC_SIZE];
See above.
Incorrect. It compiles perfectly cleanly. I just pasted it in to a C
file I had, so I know this to be true.
Yes, but only if you understand the difference between a declaration
(which says basically this thing exists somewhere, but I'm not defining
it here) and a definition (which says OK, this is the actual
object/function right here so allocate the space/put the code here).
Apparently an initialized declaration at the top level is considered a
legal defining declaration [H&S pp113-116].
There is no such thing as a "initialised declaration" in C. There are
declarations, definitions, and definitions with initialisers. What you
provided was a definition, what I provided was a declaration. I don't
have H&S so I can't comment on what it says, but either it is wrong or
you are misunderstanding it.
For my purposes, having this array of structs globally available via a
header file serves my purpose. Where I don't need it, the header file
will not be included, and I'm going to make the variable names unique
enough so that they will not be duplicated elsewhere.
It should be declared in the header and defined in exactly one C file.
Exactly as I stated.
In any case, it compiles cleanly with -Wall -ansi -pedantic.
As does what I provided, however those options do *NOT* generate a
diagnostic for multiple definitions.
<OT>
If you want gcc to catch your error, and your version supports it,
compile *all* of your code with the -fno-common option and it will then
generate an error at link time.
> I've no
idea how this setup will fare as I flesh it all out, but I think I'll
drag out lclint and use it continuously. That way, I'll know that I'm
staying out of trouble.
Without fixing the *serious* problem I have tried to tell you about it
may well work today with your current options, but it will *not* work in
all environments.