Thread: Why I can not "extern" a variable from header file?

  1. #1
    Registered User
    Join Date
    Apr 2007
    Posts
    284

    Why I can not "extern" a variable from header file?

    Here is the code:

    Code:
    //file main.cc
    //NOTE: main.cc does NOT include any file
    
    extern int a1;
    extern int a2;
    int main(){
        cout<<a1<<a2<<endl;
    }
    Code:
    //file test.cpp
    int a1=5;
    Code:
    //file test.h
    int a2=6;
    It seems that a1 can be externed to main.cc , but a2 can not. Why is that?
    Last edited by meili100; 06-22-2008 at 11:53 PM.

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Because header files are not compiled and do not generate any code. There is no definition of a2 anywhere in your program. (IOW: Just because you have a file called test.h, that doesn't mean that it magically appears when you use test.cpp.)

  3. #3
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Caution: do not define variables in header files. It will cause linking errors or other weird behavior.
    Define all global variables in source files.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  4. #4
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Because a2, which is "declared" in test.h, is never "discovered" by the compiler. The compiler doesn't know that test.h exists; it only compiles source files. main.cc is referring to an "extern int a2", which never exists. The linker is complaining because you're referring to a variable that, as far as it knows, does not exist.

    Note that declaring variables (without extern) in header files is a bad idea for the same reason. If you did this, and included the header file twice, the variable would be defined twice. The linker would complain about a multiple declaration, instead of an unresolved one.

    "extern" means you assert that the variable is declared elsewhere. If it isn't, it's not going to work.

    [edit] Beaten. But at least I made a more elaborate response. [/edit]
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  5. #5
    Registered User
    Join Date
    Apr 2007
    Posts
    284
    Thanks. But I don't agree with you about "Don't declare any variable in header files"
    You can include the header file, so everything is OK.
    In the above example, just let main.cc include "test.h"

    Quote Originally Posted by dwks View Post
    Because a2, which is "declared" in test.h, is never "discovered" by the compiler. The compiler doesn't know that test.h exists; it only compiles source files. main.cc is referring to an "extern int a2", which never exists. The linker is complaining because you're referring to a variable that, as far as it knows, does not exist.

    Note that declaring variables (without extern) in header files is a bad idea for the same reason. If you did this, and included the header file twice, the variable would be defined twice. The linker would complain about a multiple declaration, instead of an unresolved one.

    "extern" means you assert that the variable is declared elsewhere. If it isn't, it's not going to work.

    [edit] Beaten. But at least I made a more elaborate response. [/edit]

  6. #6
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    That will just lead to a mess. A really, really big mess.
    [edit] If you did as you described, you will in effect have created a header file that can only be included in one place. That's not very useful, and it's counter-intuitive. [/edit]

    Here's how you can do it. Put the extern declaration in the header file. Put a non-extern declaration in only one source file. Include the header file everywhere you need to use the variable.

    This works because this is valid code:
    Code:
    extern int x;
    int x;
    It's not a re-declaration or anything. In fact, this is valid code too:
    Code:
    int x, x, x, x, x;
    Just for global variables, of course.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    example.h:
    int x;

    a.cpp:
    #include "example.h"

    b.cpp:
    #include "example.h"

    Compile that and tell me if it works.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Registered User
    Join Date
    Apr 2007
    Posts
    284
    I still dont understand why "you will in effect have created a header file that can only be included in one place" ?

    Why the code won't work :

    Code:
    //main.cc
    #include "test.h"
    ...
    Code:
    //test.cc
    #include "test.h"
    ...
    Code:
    //test.h
    int a;

    Quote Originally Posted by dwks View Post
    That will just lead to a mess. A really, really big mess.
    [edit] If you did as you described, you will in effect have created a header file that can only be included in one place. That's not very useful, and it's counter-intuitive. [/edit]

    Here's how you can do it. Put the extern declaration in the header file. Put a non-extern declaration in only one source file. Include the header file everywhere you need to use the variable.

    This works because this is valid code:
    Code:
    extern int x;
    int x;
    It's not a re-declaration or anything. In fact, this is valid code too:
    Code:
    int x, x, x, x, x;
    Just for global variables, of course.

  9. #9
    Registered User
    Join Date
    Apr 2007
    Posts
    284
    Hey, that's the question I was just about to ask. Why is that?

    Quote Originally Posted by Elysia View Post
    example.h:
    int x;

    a.cpp:
    #include "example.h"

    b.cpp:
    #include "example.h"

    Compile that and tell me if it works.

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Because the global variable "x" will end up in TWO source files, and you cannot have two global variables with the same name (unless they are only visible in the source file it's defined).
    So in effect, the linker will find two global variables named "x" and give a linking error.
    That's why you shouldn't define variables in headers.

    dwks hints at because you ARE doing this, you can only include the header from one source file. Try to include from more than one file and you will get a linking error.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #11
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Because you have two different int x's now, one in a.cpp and one in b.cpp.

  12. #12
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Basically, you can only have one definition of a variable (like "int x"). Since header files are by their very nature copied into each source file that includes the header file, putting variable definitions in header files won't work if the header file is included multiple times -- because you will have created multiple variables with the same name.

    "extern" says that you're not creating a variable, you're referencing a variable by this name which is created somewhere else.

    (I realize I'm repeating what everyone else has just said, but the OP is still online and has been quiet for over 15 minutes, which probably means [s]he's confused. No offence. )
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  13. #13
    Registered User
    Join Date
    Apr 2007
    Posts
    284
    What if I want to define constants for many cpp files to use, can I do this:

    Code:
    //common.h
    static const int VAR = 100;
    static const int LENGTH = 30;

  14. #14
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Sure. This is sort of going back to your other thread again . . . . A global variable that is declared as "static" is limited in scope to the file in which it is declared. In other words, a static global variable is only visible inside one file. Consequently, each file can have its own set of static global variables, and even call them the same thing as static variables in other files, with no linker errors.

    So having a static variable declaration in a header file is just fine. Every source file that includes this header file will get its own copy of the static variable.

    Note that this isn't really useful unless the variables are constant.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  15. #15
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    In C++, you can just define them as constants:
    const int VAR = 100;
    const int LENGTH = 30;
    So long as you do not try to take the address to any of these constants, it will compile.
    The reason for this is that the compiler is smart enough to just replace the variables with its value instead or writing code for accessing the variable.
    So as long as you don't force its hand - ie force the compiler to create those variables by taking the address of them or something else, it should compile.
    Otherwise you would need to use static or define them in one source file and use extern.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. File transfer- the file sometimes not full transferred
    By shu_fei86 in forum C# Programming
    Replies: 13
    Last Post: 03-13-2009, 12:44 PM
  2. Need Help Fixing My C Program. Deals with File I/O
    By Matus in forum C Programming
    Replies: 7
    Last Post: 04-29-2008, 07:51 PM
  3. Need help understanding Header Files
    By Kaidao in forum C++ Programming
    Replies: 11
    Last Post: 03-25-2008, 10:02 AM
  4. gcc link external library
    By spank in forum C Programming
    Replies: 6
    Last Post: 08-08-2007, 03:44 PM