header files revisited: extern vs. static

Discussion in 'C++' started by John Goche, Oct 30, 2006.

  1. John Goche

    John Goche Guest

    Hello,

    The extern keyword can be used in C and C++
    to share global variables between files by
    declaring the variable in header file and
    defining it in only one of the two files.
    For example, if x were not declared
    extern in the header file below then
    the linker would complain about x
    being multiply defined.

    --------------------
    // main.cpp

    #include "hello.h"

    int x;

    int main() {

    x = 0;

    hello();

    }
    --------------------
    // hello.h

    #ifndef HELLO_H
    #define HELLO_H

    extern int x;

    void hello();

    #endif // HELLO_H
    --------------------
    // hello.cpp

    #include <iostream>
    #include "hello.h"

    void hello() {

    std::cout << x << std::endl;

    }
    ----------------------------------
    output: 0
    ----------------------------------

    However, I don't quite understand how
    using the keyword static in the header
    file allows us to define the variable
    in the header file and include the
    header file in multiple files.
    After all, both global variables
    and static variables are placed
    in the static data segment of a
    computer program when loaded
    into memory so what is the
    difference? Also, why is
    1 still being printed in
    the second case instead
    of 0?

    --------------------
    // main.cpp

    #include "hello.h"

    int main() {

    x = 0;

    hello();

    }
    --------------------
    // hello.h

    #ifndef HELLO_H
    #define HELLO_H

    static int x = 1;

    void hello();

    #endif // HELLO_H
    --------------------
    // hello.cpp

    #include <iostream>
    #include "hello.h"

    void hello() {

    std::cout << x << std::endl;

    }
     
    John Goche, Oct 30, 2006
    #1
    1. Advertisements

  2. John Goche

    Bart Guest

    John Goche wrote:
    The keyword 'static' declares an object with internal linkage. The
    #include just copies and pastes the contents of the header into the
    source code. This means you've just defined TWO different objects with
    internal linkage - one in each of your translation units. Probably not
    what you intended, is it?

    Regards,
    Bart.
     
    Bart, Oct 30, 2006
    #2
    1. Advertisements

  3. Non static global variables have external linkage, the linker can identify
    the variables by his name and resolve his usage from different object
    files. The static ones are internal, his names are not exported and can be
    used only from the same object file. If you have two static variables with
    the same name in different translations units, they are two different
    variables. The result is the same if you put it in a header file or in each
    of the cpp that include that header, header files are just like some way of
    automated copy&paste.

    A compiler can use a different build model that the supposed in this
    explanation, but the result must be equivalent.
     
    =?ISO-8859-15?Q?Juli=E1n?= Albo, Oct 30, 2006
    #3
  4. Nit-pick: .. unless they are declared 'const'.
     
    Victor Bazarov, Oct 30, 2006
    #4
  5. John Goche

    Steve Pope Guest

    What does the phrase "internal linkage" mean here? It almost
    sounds like an oxymoron. What is being linked to what? Does
    the linker need to manipulate such a static variable?

    Steve
     
    Steve Pope, Oct 30, 2006
    #5
  6. John Goche

    Jack Klein Guest

    Every identifier in a C++ program has several attributes, and linkage
    is one of them. There are exactly three types of linkage, external,
    internal, and no linkage.

    Internal linkage is defined in the C++ standard like this: "When a
    name has internal linkage, the entity it denotes can be referred to by
    name from other scopes in the same translation unit."

    This differs from identifiers defined at block scope, which cannot be
    referred to by name outside of the scope in which it was defined.
     
    Jack Klein, Oct 31, 2006
    #6
  7. John Goche

    Steve Pope Guest

    Thanks. I find the choice of words -- "internal linkage" --
    un-intuitive, relative to say "local to one source file", but
    that's of no consequence here. ;)

    Steve
    of little
     
    Steve Pope, Oct 31, 2006
    #7
  8. It's unintuitive for a newcomer who never dealt with the table
    of *external* symbols for a module (no offence intended). What
    is the opposite of 'external'? See?

    'External' has unfortunately two meanings. And I don't think
    there is a way to overcome that. OOH, it's a symbol that cannot
    be resolved locally, and as such is deemed to come from outside.
    OTOH it's a symbol visible from outside, a symbol to which other
    modules can refer (thus for other modules it also is 'external')
    by name. 'Internal' is basically the opposite of both of those
    meanings, i.e. defined inside and referred inside [the module].

    V
     
    Victor Bazarov, Oct 31, 2006
    #8
  9. John Goche

    Geo Guest

    If they are 'const', are they 'variables' !
     
    Geo, Oct 31, 2006
    #9
  10. John Goche

    Bart Guest

    Yes. Technically, the C++ standard defines a 'variable' as being
    "introduced by the declaration of an object". That's different than the
    mathematical meaning of a 'variable'.

    Regards,
    Bart.
     
    Bart, Oct 31, 2006
    #10
  11. John Goche

    Steve Pope Guest

    The part of the phrase I find unintuitive is the word "linkage",
    because I see no linking going on as a result of internal linkage.

    The internal vs. external distinction I have no problem with.

    Steve
     
    Steve Pope, Oct 31, 2006
    #11
  12. Well, 'linkage' is probably an awkward short replacement to 'symbol
    resolution'.

    Besides, if you agree to use 'linkage' for 'external', what would
    you use for 'internal'? And if we agree that those two definitions
    are opposites of each other, why would we use different nouns if
    we already use different adjectives? What's the opposite of, say,
    'powerful kick'? 'Weak nudge'? 'Weak push'? :)

    V
     
    Victor Bazarov, Oct 31, 2006
    #12
  13. John Goche

    Bart Guest

    Steve Pope wrote:
    Perhaps that's because you're used to thinking of 'linking' as the
    process of putting together different translation units. If instead you
    think of 'linking' as the process of putting together function and
    object definitions it may become clearer. Or if you prefer, the linker
    links the points of reference to the point of definition.

    Regards,
    Bart.
     
    Bart, Oct 31, 2006
    #13
  14. John Goche

    Bart Guest

    In addition, and this may add to the confusion, identifiers also have a
    'language linkage'. This may be changed by adding a 'linkage
    specification' such as extern "C", which is a way to link to
    identifiers specified in other languages.


    Regards,
    Bart.
     
    Bart, Oct 31, 2006
    #14
  15. John Goche

    Steve Pope Guest

    Yes, that's exactly what I think of "linking" as.
    I'll go along with the last sentence. Thanks.

    Steve
     
    Steve Pope, Nov 1, 2006
    #15
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.