A question on incomplete definitions

Discussion in 'C Programming' started by ark, Dec 17, 2003.

  1. ark

    ark Guest

    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
    ark, Dec 17, 2003
    #1
    1. Advertising

  2. ark

    Malcolm Guest

    "ark" <> 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.
    Malcolm, Dec 17, 2003
    #2
    1. Advertising

  3. ark

    Alex Guest

    ark <> 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
    Alex, Dec 17, 2003
    #3
  4. ark

    ark Guest

    "Malcolm" <> wrote in message
    news:brqjsi$685$...
    >

    <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
    ark, Dec 17, 2003
    #4
  5. ark

    ark Guest

    "Alex" <> wrote in message
    news:brqlfn$6id5i$-berlin.de...
    > ark <> 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
    ark, Dec 17, 2003
    #5
  6. ark

    Ben Pfaff Guest

    Alan Balmer <> writes:

    > On Wed, 17 Dec 2003 22:01:25 -0000, "Malcolm"
    > <> 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
    Ben Pfaff, Dec 17, 2003
    #6
  7. ark

    Alan Balmer Guest

    On Wed, 17 Dec 2003 22:01:25 -0000, "Malcolm"
    <> 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
    Alan Balmer, Dec 17, 2003
    #7
  8. ark

    ark Guest

    "Ben Pfaff" <> wrote in message
    news:...
    > Alan Balmer <> 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
    ark, Dec 18, 2003
    #8
  9. ark

    Ben Pfaff Guest

    "ark" <> writes:

    > "Ben Pfaff" <> wrote in message
    > news:...
    > > Alan Balmer <> 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
    Ben Pfaff, Dec 18, 2003
    #9
  10. ark

    Joe Wright Guest

    ark wrote:
    >
    > "Alex" <> wrote in message
    > news:brqlfn$6id5i$-berlin.de...
    > > ark <> 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 ---
    Joe Wright, Dec 18, 2003
    #10
  11. ark

    Alex Guest

    Joe Wright <> wrote:
    > ark wrote:
    >>
    >> "Alex" <> wrote in message
    >> news:brqlfn$6id5i$-berlin.de...
    >> > ark <> 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
    Alex, Dec 18, 2003
    #11
  12. ark

    Jack Klein Guest

    On 17 Dec 2003 22:31:19 GMT, Alex <> wrote in
    comp.lang.c:

    > ark <> 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
    Jack Klein, Dec 18, 2003
    #12
  13. ark

    Guest

    ark <> 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
    , Dec 18, 2003
    #13
  14. ark

    James Hu Guest

    On 2003-12-18, ark <> wrote:
    >
    > "Ben Pfaff" <> wrote in message
    > news:...
    >> Alan Balmer <> 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
    James Hu, Dec 18, 2003
    #14
  15. 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.
    Kevin Goodsell, Dec 18, 2003
    #15
  16. ark

    Kevin Bracey Guest

    In message <brr004$6doss$-berlin.de>
    Alex <> wrote:

    > Joe Wright <> 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/
    Kevin Bracey, Dec 18, 2003
    #16
  17. ark

    Alan Balmer Guest

    On 17 Dec 2003 15:21:41 -0800, Ben Pfaff <> wrote:

    >Alan Balmer <> writes:
    >
    >> On Wed, 17 Dec 2003 22:01:25 -0000, "Malcolm"
    >> <> 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
    Alan Balmer, Dec 18, 2003
    #17
  18. ark

    ark Guest

    "ark" <> 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
    ark, Dec 18, 2003
    #18
  19. ark

    Alex Guest

    Jack Klein <> wrote:
    > On 17 Dec 2003 22:31:19 GMT, Alex <> wrote in
    > comp.lang.c:


    >> ark <> 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
    Alex, Dec 18, 2003
    #19
  20. ark

    Chris Torek Guest

    [on forward declarations of variables via tentative definitions]

    In article <>
    Alan Balmer <> 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 (40°39.22'N, 111°50.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.
    Chris Torek, Dec 18, 2003
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Thomas Barth

    Question about definitions

    Thomas Barth, Nov 15, 2004, in forum: C++
    Replies:
    3
    Views:
    2,587
    Victor Bazarov
    Nov 15, 2004
  2. Paul F. Dietz

    Question about incomplete array element types

    Paul F. Dietz, Jul 11, 2003, in forum: C Programming
    Replies:
    5
    Views:
    446
    Dan Pop
    Jul 11, 2003
  3. ishtar2020
    Replies:
    2
    Views:
    980
    Simon Forman
    Aug 28, 2006
  4. Roman Mashak

    question about 'static' definitions

    Roman Mashak, May 21, 2005, in forum: C Programming
    Replies:
    3
    Views:
    314
    Malcolm
    May 21, 2005
  5. raphfrk

    question on variable definitions

    raphfrk, Mar 2, 2007, in forum: C Programming
    Replies:
    23
    Views:
    688
    Bill Pursell
    Mar 3, 2007
Loading...

Share This Page