By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,852 Members | 2,219 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,852 IT Pros & Developers. It's quick & easy.

A question on incomplete definitions

P: n/a
ark
Hello group,
Could you help me with this:

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?

Thanks,
Ark
Nov 14 '05 #1
Share this Question
Share on Google+
24 Replies


P: n/a

"ark" <ar****@comcast.net> wrote in message
static const int x;
This is a tentative forward declaration of x.
........... something .............
static const int x = 17;
This is the declaration of x
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 compiler is allowed to give warnings for code which is correct but looks
suspicious. Here you are using a little-used construct with a const, so it
wonders if you know what you are doing.

I would also give a warning, since I suspect that you don't need a tentative
forward declaration at all of a static const integer in your code. However I
may be wrong.
Nov 14 '05 #2

P: n/a
ark <ar****@comcast.net> wrote:
Hello group,
Could you help me with this: static const int x;
You declare and define x, with the implicit value of 0.
However, since the object is const, you won't have a chance
to change its value. AFAIK, this construct is valid, but
is largely meaningless.
........... something .............
static const int x = 17;
You redeclare and redefine x with the value of 17. This
is obviously incorrect because the x identifier already
exists and has storage.
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.


This is a friendly warning that says that your first line
doesn't make much sense. It is probably not a required
diagnostic.

Alex
Nov 14 '05 #3

P: n/a
ark

"Malcolm" <ma*****@55bank.freeserve.co.uk> wrote in message
news:br**********@newsg1.svr.pol.co.uk...
<snip> I would also give a warning, since I suspect that you don't need a tentative forward declaration at all of a static const integer in your code. However I may be wrong.


Imagine, e.g., a header file that #define's useful thing about x (which is
really likely to be a struct of some sort). Then the header needs a
"tentative forward declaration" of x, and here it is useful IMHO.
Sorry for wrong terminology,
- Ark
Nov 14 '05 #4

P: n/a
ark

"Alex" <al*******@hotmail.com> wrote in message
news:br************@ID-190529.news.uni-berlin.de...
ark <ar****@comcast.net> wrote:
Hello group,
Could you help me with this:

static const int x;


You declare and define x, with the implicit value of 0.
However, since the object is const, you won't have a chance
to change its value. AFAIK, this construct is valid, but
is largely meaningless.
........... something .............
static const int x = 17;


You redeclare and redefine x with the value of 17. This
is obviously incorrect because the x identifier already
exists and has storage.
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.


This is a friendly warning that says that your first line
doesn't make much sense. It is probably not a required
diagnostic.

Alex


I am not sure your analysis is correct; see Malcolm's posting above.
- Ark
Nov 14 '05 #5

P: n/a
On Wed, 17 Dec 2003 22:01:25 -0000, "Malcolm"
<ma*****@55bank.freeserve.co.uk> wrote:
static const int x;

This is a tentative forward declaration of x.

How does the compiler distinguish this from a normal declaration with
default initialization?

--
Al Balmer
Balmer Consulting
re************************@att.net
Nov 14 '05 #6

P: n/a
Alan Balmer <al******@att.net> writes:
On Wed, 17 Dec 2003 22:01:25 -0000, "Malcolm"
<ma*****@55bank.freeserve.co.uk> wrote:
static const int x;

This is a tentative forward declaration of x.

How does the compiler distinguish this from a normal declaration with
default initialization?


See C99 6.9.2#2:

2 A declaration of an identifier for an object that has file
scope without an initializer, and without a storage-class
specifier or with the storage-class specifier static,
constitutes a tentative definition. If a translation unit
contains one or more tentative definitions for an
identifier, and the translation unit contains no external
definition for that identifier, then the behavior is exactly
as if the translation unit contains a file scope declaration
of that identifier, with the composite type as of the end of
the translation unit, with an initializer equal to 0.

--
"The way I see it, an intelligent person who disagrees with me is
probably the most important person I'll interact with on any given
day."
--Billy Chambless
Nov 14 '05 #7

P: n/a
ark

"Ben Pfaff" <bl*@cs.stanford.edu> wrote in message
news:87************@pfaff.stanford.edu...
Alan Balmer <al******@att.net> writes:
<snip> See C99 6.9.2#2:

2 A declaration of an identifier for an object that has file
scope without an initializer, and without a storage-class
specifier or with the storage-class specifier static,
constitutes a tentative definition. If a translation unit
contains one or more tentative definitions for an
identifier, and the translation unit contains no external
definition for that identifier, then the behavior is exactly
as if the translation unit contains a file scope declaration
of that identifier, with the composite type as of the end of
the translation unit, with an initializer equal to 0.

--
"The way I see it, an intelligent person who disagrees with me is
probably the most important person I'll interact with on any given
day."
--Billy Chambless


So... I can do it only in C99, not in classic C (90?) or whatever was
before?
What about K&R?
Thanks for all help,
- Ark
Nov 14 '05 #8

P: n/a
ark wrote:

"Alex" <al*******@hotmail.com> wrote in message
news:br************@ID-190529.news.uni-berlin.de...
ark <ar****@comcast.net> wrote:
Hello group,
Could you help me with this:

static const int x;


You declare and define x, with the implicit value of 0.
However, since the object is const, you won't have a chance
to change its value. AFAIK, this construct is valid, but
is largely meaningless.
........... something .............
static const int x = 17;


You redeclare and redefine x with the value of 17. This
is obviously incorrect because the x identifier already
exists and has storage.
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.


This is a friendly warning that says that your first line
doesn't make much sense. It is probably not a required
diagnostic.

Alex


I am not sure your analysis is correct; see Malcolm's posting above.
- Ark

Alex may be more correct that Malcolm. The whole point of the const
qualifier is that its object should not be modified without diagnostic.
You noticed that..

const int x;

yielding a diagnostic because you missed your only 'legal' chance to
define the value of x. It is not clear that the diagnostic is required
but x clearly useless in this case. Further down in your code..

const int x = 17;

redifines x and assigns a value to it. The redifinition is the error
here and requires a diagnostic. Assigning 17 to x here is probably ok.
--
Joe Wright http://www.jw-wright.com
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Nov 14 '05 #9

P: n/a
"ark" <ar****@comcast.net> writes:
"Ben Pfaff" <bl*@cs.stanford.edu> wrote in message
news:87************@pfaff.stanford.edu...
Alan Balmer <al******@att.net> writes:
<snip>
See C99 6.9.2#2:

2 A declaration of an identifier for an object that has file
scope without an initializer, and without a storage-class
specifier or with the storage-class specifier static,
constitutes a tentative definition. If a translation unit
contains one or more tentative definitions for an
identifier, and the translation unit contains no external
definition for that identifier, then the behavior is exactly
as if the translation unit contains a file scope declaration
of that identifier, with the composite type as of the end of
the translation unit, with an initializer equal to 0.


So... I can do it only in C99, not in classic C (90?) or whatever was
before?


There is similar text in C90 if I recall correctly. I generally
quote from C99 because I have an accurate electronic
transcription.
What about K&R? Thanks for all help, - Ark


K&R didn't have the concept of a tentative definition as far as I
know.
--
"What is appropriate for the master is not appropriate for the novice.
You must understand the Tao before transcending structure."
--The Tao of Programming
Nov 14 '05 #10

P: n/a
Joe Wright <jo********@earthlink.net> wrote:
ark wrote:

"Alex" <al*******@hotmail.com> wrote in message
news:br************@ID-190529.news.uni-berlin.de...
> ark <ar****@comcast.net> wrote:
> > Hello group,
> > Could you help me with this:
>
> > static const int x;
>
> You declare and define x, with the implicit value of 0.
> However, since the object is const, you won't have a chance
> to change its value. AFAIK, this construct is valid, but
> is largely meaningless.
>
> > ........... something .............
> > static const int x = 17;
>
> You redeclare and redefine x with the value of 17. This
> is obviously incorrect because the x identifier already
> exists and has storage.
>
> > 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.
>
> This is a friendly warning that says that your first line
> doesn't make much sense. It is probably not a required
> diagnostic.
>
> Alex


I am not sure your analysis is correct; see Malcolm's posting above.
- Ark

Alex may be more correct that Malcolm. The whole point of the const
qualifier is that its object should not be modified without diagnostic.
You noticed that..

const int x; yielding a diagnostic because you missed your only 'legal' chance to
define the value of x. It is not clear that the diagnostic is required
but x clearly useless in this case. Further down in your code.. const int x = 17; redifines x and assigns a value to it. The redifinition is the error
Indeed.
here and requires a diagnostic. Assigning 17 to x here is probably ok.


It can't be okay. See the first sentence in your second
paragraph :-)

Alex
Nov 14 '05 #11

P: n/a
On 17 Dec 2003 22:31:19 GMT, Alex <al*******@hotmail.com> wrote in
comp.lang.c:
ark <ar****@comcast.net> wrote:
Hello group,
Could you help me with this:

static const int x;


You declare and define x, with the implicit value of 0.
However, since the object is const, you won't have a chance
to change its value. AFAIK, this construct is valid, but
is largely meaningless.
........... something .............
static const int x = 17;


You redeclare and redefine x with the value of 17. This
is obviously incorrect because the x identifier already
exists and has storage.


I won't quote the standard's text on tentative definitions that means
this is perfectly correct, because Ben already posted it in full.
Make sure you read it. The OP's code is perfectly legal C.
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.


This is a friendly warning that says that your first line
doesn't make much sense. It is probably not a required
diagnostic.

Alex


--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq
Nov 14 '05 #12

P: n/a
ark <ar****@comcast.net> wrote:

So... I can do it only in C99, not in classic C (90?) or whatever was
before?
No, the rule has been the same since C89 (so the people who are telling
you that the code is wrong have no excuse for spreading such
misinformation).
What about K&R?


K&R did not provide any mechanism for forward-declaring statics. Many
compilers did, but the exact mechanism varied.

-Larry Jones

What's the matter? Don't you trust your own kid?! -- Calvin
Nov 14 '05 #13

P: n/a
On 2003-12-18, ark <ar****@comcast.net> wrote:

"Ben Pfaff" <bl*@cs.stanford.edu> wrote in message
news:87************@pfaff.stanford.edu...
Alan Balmer <al******@att.net> writes:

<snip>
See C99 6.9.2#2:

So... I can do it only in C99, not in classic C (90?) or whatever was
before?
What about K&R?


Please make sure you are compiling the code with a C compiler and not
a C++ compiler. C++ has a "one definition" rule that C does not.

-- James
Nov 14 '05 #14

P: n/a
ark wrote:


So... I can do it only in C99, not in classic C (90?) or whatever was
before?


It might be confusing to call C89/90 "Classic C". That term has been
used to refer to a C dialect that came just after K&R C. It's basically
the C that is usually called K&R, but it differs from the language
described in K&R1 in a few ways - it adds structure assignment,
enumerations, and 'void'.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
Nov 14 '05 #15

P: n/a
In message <br************@ID-190529.news.uni-berlin.de>
Alex <al*******@hotmail.com> wrote:
Joe Wright <jo********@earthlink.net> wrote:
ark wrote:

You noticed that..

const int x;

yielding a diagnostic because you missed your only 'legal' chance to
define the value of x. It is not clear that the diagnostic is required
but x clearly useless in this case. Further down in your code..

const int x = 17;

redifines x and assigns a value to it. The redifinition is the error


Indeed.


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.

--
Kevin Bracey, Principal Software Engineer
Tematic Ltd Tel: +44 (0) 1223 503464
182-190 Newmarket Road Fax: +44 (0) 1223 503458
Cambridge, CB5 8HE, United Kingdom WWW: http://www.tematic.com/
Nov 14 '05 #16

P: n/a
On 17 Dec 2003 15:21:41 -0800, Ben Pfaff <bl*@cs.stanford.edu> wrote:
Alan Balmer <al******@att.net> writes:
On Wed, 17 Dec 2003 22:01:25 -0000, "Malcolm"
<ma*****@55bank.freeserve.co.uk> wrote:
>> static const int x;
>>
>This is a tentative forward declaration of x.
>>

How does the compiler distinguish this from a normal declaration with
default initialization?


See C99 6.9.2#2:

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.

--
Al Balmer
Balmer Consulting
re************************@att.net
Nov 14 '05 #17

P: n/a
ark

"ark" <ar****@comcast.net> wrote in message
news:ye4Eb.583901$Fm2.541205@attbi_s04...
Hello group,
Could you help me with this:

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?

Thanks,
Ark

Thanks for the discussion.
A couple of people find this feature useless; IMHO it indicates their bias
toward runtime initialization in complex cases (in which case they can use
C++ as well :).
Those interested in non-trivial compile-time initialization (which reduces
footprint of data and code and, in embedded world, allows to put initialized
stuff in ROM) will probably find this language feature useful.
- Ark
Nov 14 '05 #18

P: n/a
Jack Klein <ja*******@spamcop.net> wrote:
On 17 Dec 2003 22:31:19 GMT, Alex <al*******@hotmail.com> wrote in
comp.lang.c:
ark <ar****@comcast.net> wrote:
> Hello group,
> Could you help me with this:

> static const int x;


You declare and define x, with the implicit value of 0.
However, since the object is const, you won't have a chance
to change its value. AFAIK, this construct is valid, but
is largely meaningless.
> ........... something .............
> static const int x = 17;


You redeclare and redefine x with the value of 17. This
is obviously incorrect because the x identifier already
exists and has storage.

I won't quote the standard's text on tentative definitions that means
this is perfectly correct, because Ben already posted it in full.
Make sure you read it. The OP's code is perfectly legal C.


Ugh. My mistake. I have never run into a situation where this
feature would have been useful.

Alex
Nov 14 '05 #19

P: n/a
[on forward declarations of variables via tentative definitions]

In article <bn********************************@4ax.com>
Alan Balmer <al******@spamcop.net> writes:
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) {
...
g(...);
...
}

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

calls f() from g() with a prototype in place, but calls g() from
f() without one. If we swap the order, putting g()'s definition
first, then f() calls g() with a prototype, but g() calls f()
without one. The solution is to declare at least one of f() and
g() first, then define the two in the remaining topologically-required
order (if we declare both, no order is required).

Just as the function version of the problem shows up in mutually-recursive
functions, the data version shows up in mutually-referential data.
Suppose we have the following data structures:

/* optional: typedef struct S STYPE; */
typedef struct T TTYPE; */

struct S {
struct T *s_tref; /* or TTYPE *s_tref; */
...
};

struct T {
struct S *t_sref; /* etc */
...
};

but now we want to define a static-duration, and optionally
internal-linkage, instance of an S that points to a T, and vice
versa:

/* optional: static */
struct S s_instance = { &t_instance, ... };

/* optional: static */
struct T t_instance = { &s_instance, ... };

As with functions f() and g(), neither order works without a
forward declaration. If s_instance and t_instance are to have
external linkage, we can use the "extern" keyword to "forward
declare" at least one of them:

extern struct T t_instance; /* forward declaration */
struct S s_instance = { &t_instance, ... };
struct T t_instance = { &s_instance, ... };

But if you wish to keep s_instance and t_instance private, with
internal linkage (using the "static" keyword), "extern" is no
longer suitable; now you must use "static":

static struct T t_instance; /* forward decl & tentative def */
static struct S s_instance = { &t_instance, ... };
static struct T t_instance = { &s_instance, ... };

As with functions f() and g(), we can forward-declare both instances
if we like, but at least one -- and in this case at most one (more
complicated multi-way references may require up to N-1 forward
declarations of N objects) -- is required.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #20

P: n/a

"Kevin Bracey" <ke**********@tematic.com> wrote in message
news:62****************@tematic.com...
In message <br************@ID-190529.news.uni-berlin.de>
Alex <al*******@hotmail.com> wrote:
Joe Wright <jo********@earthlink.net> wrote:
ark wrote:
>
You noticed that..
const int x;

yielding a diagnostic because you missed your only 'legal' chance to define the value of x. It is not clear that the diagnostic is required but x clearly useless in this case. Further down in your code..

const int x = 17;

redifines x and assigns a value to it. The redifinition is the
error
Indeed.


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!");
Nov 14 '05 #21

P: n/a
On Thu, 18 Dec 2003 19:01:54 UTC, Chris Torek <no****@torek.net>
wrote:
[on forward declarations of variables via tentative definitions]

In article <bn********************************@4ax.com>
Alan Balmer <al******@spamcop.net> writes:
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 */


--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation

Nov 14 '05 #22

P: n/a
>On Thu, 18 Dec 2003 19:01:54 UTC, Chris Torek <no****@torek.net>
wrote:
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) {

In article <wmzsGguTDN6N-pn2-dXkxH46B5OkL@moon>
The Real OS/2 Guy <os****@pc-rosenau.de> writes: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.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #23

P: n/a
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"?
Nov 14 '05 #24

P: n/a
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 <br************@ID-190529.news.uni-berlin.de>
Alex <al*******@hotmail.com> wrote:
Joe Wright <jo********@earthlink.net> wrote:
> ark wrote:
>>
> You noticed that..

> const int x;

> yielding a diagnostic because you missed your only 'legal' chance to
> define the value of x. It is not clear that the diagnostic is required
> but x clearly useless in this case. Further down in your code..

> const int x = 17;

> redifines x and assigns a value to it. The redifinition is the error


Indeed.


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"?
Nov 14 '05 #25

This discussion thread is closed

Replies have been disabled for this discussion.