Re: extern const multiple definitions

Discussion in 'C++' started by SG, Jan 12, 2011.

  1. SG

    SG Guest

    Just adding to what Marcel wrote...

    On 12 Jan., 10:41, Heck wrote:

    >         const int MAX_SIZE = 16;


    This is a definition of MAX_SIZE with internal linkage. Hence every
    translation unit that contains this has its own MAX_SIZE variable and
    you cannot refer to another translation unit's "internal" variables by
    name. External linkage is the default unless you have "top-level
    constness" which changes linkage to be internal. In C linkage is
    usually controlled with the static keyword. As such, it's kind of the
    opposite of the extern keyword. But in C++ we have another alternative
    to this kind of use of the static keyword: anonymous namespaces.
    Anonymous namespaces don't affect linkage but they also enable you to
    define entities that cannot be referred to from another translation
    unit by name.

    >         extern const int MAX_SIZE = 16;


    This is a definition of another MAX_SIZE to have external linkage. You
    can only have of one such definition within the whole program.

    > This worked to give the compiler what it needed to compile a function
    > with, e.g.,  int array[MAX_SIZE] as a formal argument.  (Previously, I
    > had MAX_SIZE without the assignment in the .h.  Without that
    > assignment and, I guess, definition, of MAX_SIZE in the .h, the
    > compiler (Microsoft) produced errors "C2540: non-constant expression
    > as array bound" when it encountered the declaration of the function in
    > a class and "C2057: expected constant expression" when it found the
    > declaration of an array using it in that same class.)


    Right. "const" doesn't imply "constant expression". A constant
    expression is something much stronger than simply const. Constant
    expression means that the value is known at compile-time. But if the
    compiler simply sees a declaration of a const "variable" it is not a
    constant expression -- at least not until you provide also a
    definition for it with an initialization.

    > Here's the problem.  When I linked, the linker found the variable
    > already defined in the various objs produced from the various
    > translation units that used this class.


    Sounds like you had multiple definitions of the same object which is
    not allowed by the ODR (one definition rule).

    For simple constants like a single int there is no harm in defining it
    in a header file with internal linkage. This can be achieved by
    writing

    const int max_size = 16;

    Note that this is an aspect where C and C++ differ. In C a definition
    like this neither yields a constant expression nor a definition with
    internal linkage (but external). That is why #define is more popular
    in C.

    If you want to only *declare* a constant in a header file, either
    because you don't want to reveal its value in the header or because
    it's a bigger lookup table, you'd write things like

    //header:
    extern const int max_size;
    extern const char error_message_1729[];
    extern const double table[16];

    //cpp file:
    extern const int max_size = 16;
    extern const char error_message_1729[] = "yadda yadda";
    extern const double table[16] = {
    1,2,3,4,5,6,7,8,
    9,8,7,6,5,4,3,2
    };

    Note that it is okay to declare error_message_1729 without a n array
    size. This is allowed for namespace scope arrays. Their type will be
    incomplete, but pointer-to-array decay still works. Note also, that
    you may remove "extern" from the definitions in the cpp-file but only
    if you first declare them with extern (for example by including the
    header). Otherwise, they would have internal linkage and the linker
    will tell you about undefined references.

    Cheers!
    SG
    SG, Jan 12, 2011
    #1
    1. Advertising

  2. SG

    SG Guest

    On 12 Jan., 13:22, SG wrote:
    > [...] Constant
    > expression means that the value is known at compile-time. But if the
    > compiler simply sees a declaration of a const "variable" it is not a
    > constant expression -- at least not until you provide also a
    > definition for it with an initialization.


    Though, a definition is not requires. Example:

    struct foo {
    static const bar = 1729;
    };

    foo::bar is only declared here. No memory is allocated for foo::bar.
    But nevertheless C++ allows us to use foo::bar in contexts where
    constant expressions are expected. Taking its address would require a
    definition and a definition has to be outside of the struct/class
    definition.

    I hope that's not too much information. ;)

    > Cheers!
    > SG
    SG, Jan 12, 2011
    #2
    1. Advertising

  3. SG

    Paul Guest

    "SG" <> wrote in message
    news:...
    Just adding to what Marcel wrote...

    On 12 Jan., 10:41, Heck wrote:

    > const int MAX_SIZE = 16;


    This is a definition of MAX_SIZE with internal linkage. Hence every
    translation unit that contains this has its own MAX_SIZE variable and
    you cannot refer to another translation unit's "internal" variables by
    name. External linkage is the default unless you have "top-level
    constness" which changes linkage to be internal. In C linkage is
    usually controlled with the static keyword. As such, it's kind of the
    opposite of the extern keyword. But in C++ we have another alternative
    to this kind of use of the static keyword: anonymous namespaces.
    Anonymous namespaces don't affect linkage but they also enable you to
    define entities that cannot be referred to from another translation
    unit by name.

    <snip>

    Please confirm . What is a translation unit?

    I always believed that translation unit was an obj file , or some kind of
    lib linked at link time.
    A long time ago I had many arguments with the 'C-C++ community' at the time,
    who argued that a translation uniit was source code file. Do you know if
    it's still the case that the 'C-C++ community' think this or do they have a
    new meaning for this term now?

    TIA
    Paul, Jan 12, 2011
    #3
  4. SG

    Paul Guest

    "Pete Becker" <> wrote in message
    news:2011011210050085798-pete@versatilecodingcom...
    > On 2011-01-12 09:51:01 -0500, Paul said:
    >
    >>
    >> Please confirm . What is a translation unit?
    >>
    >> I always believed that translation unit was an obj file , or some kind of
    >> lib linked at link time.

    >
    > A translation unit is a source file and all of the other files that it
    > pulls in through #include directives, ignoring any lines that are excluded
    > by preprocessing directives. It's the same in C and C++. In the current
    > C++ standard, it's defined in the first paragraph of Clause 2, "Lexical
    > conventions".
    >
    > --
    > Pete
    > Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
    > Standard C++ Library Extensions: a Tutorial and Reference
    > (www.petebecker.com/tr1book)
    >
    >


    The word 'unit' seems to suggest a single errm object(thing).
    Seems like a strange term but I guess it makes sense to the compiler guys.
    TY for your reply :~).
    Paul, Jan 12, 2011
    #4
    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 Matthews
    Replies:
    5
    Views:
    2,370
    tom_usenet
    Aug 2, 2004
  2. Rakesh Sinha
    Replies:
    4
    Views:
    1,840
    Rakesh Sinha
    Jan 13, 2005
  3. Replies:
    11
    Views:
    1,087
  4. Javier
    Replies:
    2
    Views:
    544
    James Kanze
    Sep 4, 2007
  5. Andre
    Replies:
    5
    Views:
    518
    Keith Thompson
    Jul 17, 2012
Loading...

Share This Page