A question on incomplete definitions

J

Joe Wright

Kevin Bracey said:
In message <[email protected]>


No. There is no error. "const int x;" is a tentative definition.

The later "const int x = 17;" is a real definition (because it has an
initialiser) and overrides the tentative definition.

Personally, I think it's a stupid C feature, and my compiler has an option to
disable tentative definitions (because it improves code generation for the
ARM). But the OP's code is totally conforming standard C.

I would advise that he adds an "extern" to the first line to change it into a
declaration, unless he really needs a tentative definition. That'll probably
stop the compiler warning.
Absolutely right. There is no error.

for (i = 0; i < 1000; ++i) puts("I will read and test before posting!");
 
T

The Real OS/2 Guy

[on forward declarations of variables via tentative definitions]

I suppose the reason I never remember this sort of two-step process is
because I'm never had a situation where it was useful. I don't find
the OP's header file example convincing.

Forward declarations of variables are required for the same
reason forward declarations of functions are required: sometimes
it is impossible to topological-sort-away the dependencies.

Suppose we have function f() that calls function g(), and function
g() that calls function f(). This order:

/* optional: static */
F_TYPE f(args) {

That's not a prototype - it is an incomplete definition only. Right,
it works lika a prototype for references after this point. A complete
definition would contain the type(s) of the parameters, each following
with the name of the formal parameter, e.g:

P_TYPE f(char *args) {
...
g(...);

You've no prototype for this function in scope yet. So the copiler
knows nothing about it, so it complains.
...
}

/* optional: static */
G_TYPE g(args) {
...
f();
...
}

Declare prototypes of functions you have to use at least immediately
before you have to use them.

A prototype looks like a definition but without the definition (the
body of the fuction itself, e.g.

G_TYPE f(char *); /* declaration of typelist the fuction accepts
*/
/* and declaration of the value the function
returns */
or
G_TYPE f(char *args); /* name of formal parameter is optional, */
/* but nice for documentation */

As you declared later you needs the same for data. Make simply a
forward declaration, e.g.

struct mystruct; /* declares that somewhere later a struct mystruct
will occure */
/* so you can define a pointer to a struct
mystruct then */
struct mystruct *; /* you can anywhere make a forward declaration
like this */
/* even as nothing about the struct is known
yet. But */
/* it's fine to have a pointer to struct
mystruct before */
/* you needs the knowledge of the layout of
the struct */

You may even declare types:

typedef struct mystruct { /* declares an struct mystruct and saying
make an alias from it */
/* struct members */
} MYSTRUCT, *PMYSTRUCT; /* defining an alias for struct mystruct */
/* and struct mystruct *, an alias for a */
/* pointer to such a struct */

Using forward declaration for typedef:

typedef struct mystruct *PMYSTRUCT; /* an alias for an pointer type to
this struct */

typedef struct mystruct MYSTRUCT; /* an alias for a struct mystruct
*/

struct mystruct { /* declaring the struct mystruct
*/
/* members of the struct */
};

with all above:

struct mystruct { /* define a struct mystruct */
/* members of this struct */
} mystruct;

----

MYSTRUCT mystruct; /* define a struct mystruct */
MYSTRUCT *pmystruct; /* define a pointer to struct mystruct */
----
PMYSTRUCT pmystruct; /* define a pointer to struct mystruct */

with the knowledge above crossreference pointers */

typedef struct mystruct *PMYSTRUCT; /* pointer to an incomplete
struct */

/* declare a type, a pointer type (aliases) and the struct mystruct at
once */
typedef struct myotherstruct {
PMYSTRUCT p;
struct myotherstruct pme; /* there is no typedef for */
/* struct myotherstruct known yet */
/* as struct myotherstruct is not */
/* declared finally we can declare */
/* pinters to incomplete type */
/* only in this way */
/* more members ... */
} MYOTHERSTRUCT, *PMYOTHERSTRUCT;

/* d
typedef struct mystruct {
PMYOTHERSTRUCT p;
PMYSTRUCT pme; /* as we alredy knoe a type (an alias) */
/* of this struct we can use the alias
*/
/* to crate a pointer to this type
*/
/* more members .... */
] MYSTRUCT; /* pointer type is already declared above */
 
C

Chris Torek

Forward declarations of variables are required for the same
reason forward declarations of functions are required: sometimes
it is impossible to topological-sort-away the dependencies.

Suppose we have function f() that calls function g(), and function
g() that calls function f(). This order:

/* optional: static */
F_TYPE f(args) {
[/QUOTE]

That's not a prototype - it is an incomplete definition only.

The word "args" was not meant to be taken literally (and in
particular, if you do take it literally, it uses implicit "int",
which is no longer supported in C99). Please re-read my article,
mentally substituting:

F_TYPE f(ARG_A_TYPE a, ARG_B_TYPE b, ARG_C_TYPE c, ARG_D_TYPE d,

and so on for as many "arg"s as you like.

(The rest of your followup appears to be irrelevant to my point,
which is: We must sometimes forward-declare functions, e.g., via
prototypes. We must also sometimes forward-declare variables,
e.g., via tentative definitions. The cases in which these are
*required* are isomorphic. For various reasons, I consider it
"good style" to forward-declare *all* functions via prototypes even
when it is not *required*, but not to forward-declare variables in
all such cases. Not everyone will agree with me in terms of style,
preferring instead to topologically-sort their internal-linkage
"static" functions, for instance.)
 
P

Peter Shaggy Haywood

Groovy hepcat ark was jivin' on Wed, 17 Dec 2003 21:52:34 GMT in
comp.lang.c.
A question on incomplete definitions's a cool scene! Dig it!
static const int x;
........... something .............
static const int x = 17;

It looks perfectly legal to me but MSVC/C++ 6.0 gives, on the first line,
"warning C4132: 'x' : const object should be initialized"
yet generates correct code.

What is correct - the code or the compiler? If the code, is it known what
compilers choke on this and how hard?

The code is correct. The first declaration of x is a tentative
definition (assuming it is at file scope), which becomes a full
definition at the second declaration (since that has an initialiser).

--

Dig the even newer still, yet more improved, sig!

http://alphalink.com.au/~phaywood/
"Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
I know it's not "technically correct" English; but since when was rock & roll "technically correct"?
 
P

Peter Shaggy Haywood

Groovy hepcat Kevin Bracey was jivin' on Thu, 18 Dec 2003 12:05:03 GMT
in comp.lang.c.
Re: A question on incomplete definitions's a cool scene! Dig it!
In message <[email protected]>


No. There is no error. "const int x;" is a tentative definition.

The later "const int x = 17;" is a real definition (because it has an
initialiser) and overrides the tentative definition.

Personally, I think it's a stupid C feature, and my compiler has an option to
disable tentative definitions (because it improves code generation for the
ARM). But the OP's code is totally conforming standard C.

I would advise that he adds an "extern" to the first line to change it into a
declaration,

If internal linkage is desired, then no, he shouldn't add extern to
the first line. (AAMOF, simply adding extern to a declaration that
already has the static storage class specifier would be wrong under
any circumstances.)

--

Dig the even newer still, yet more improved, sig!

http://alphalink.com.au/~phaywood/
"Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
I know it's not "technically correct" English; but since when was rock & roll "technically correct"?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,023
Latest member
websitedesig25

Latest Threads

Top