Thread: No error from multiple definitions of global variables

  1. #1
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057

    No error from multiple definitions of global variables

    I was reading this thread (which discusses how you can't declare global variables in header files, etc) and thought I'd try it out. I seem to remember reading something about how const global variables in C++ were automatically static, that is, limited to the scope of one file, which would explain Elysia's last post.

    Evidently I remembered correctly on that point.

    Anyway. I came across a very strange phenomenon in my experimenting, which I eventually narrowed down to this:
    Code:
    $ ./globalx
    $ cat globalx.c
    int x;
    
    $ cat globalxmain.c
    int x;
    
    int main() {
        return 0;
    }
    $ gcc -c globalxmain.c
    $ gcc -c globalx.c
    $ gcc globalx.o globalxmain.o -o globalx
    $ ./globalx
    $
    Why does this work? How can a global variable, declared in two separate source files, be legal C? (It's not legal C++, by the way.)

    I thought global variables could only be declared once, like functions, or the linker would complain . . . .

    What am I missing here?

    [edit] Mm'kay, if I initialize x in both places I get the expected linker error.
    Code:
    $ gcc globalx.c globalxmain.c -o globalx
    /tmp/ccvX2E7d.o:(.data+0x0): multiple definition of `x'
    /tmp/ccMaJSet.o:(.data+0x0): first defined here
    collect2: ld returned 1 exit status
    $
    I guess un-initialized global variable declarations can be repeated or something like that? . . . . [/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.

  2. #2
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Compile with the --ansi switch and see if it still works. Perhaps gcc is eliminating "dead" code.

  3. #3
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by ISO C99 standard, section 6.9.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 there you go: as long as things are global, no storage is necessarily set aside unless explicitly initialized. You can even do this:
    Code:
    int x;
    int x;
    int x;
    
    int main() {
        return 0;
    }
    Edit: And just for citizen, I compiled that with gcc -Wall -ansi -pedantic.

  4. #4
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Yes, I was aware that you could declare global variables several times in one file, but I didn't think it applied to different source files. It looks like I was wrong.
    Edit: And just for citizen, I compiled that with gcc -Wall -ansi -pedantic.
    So did I, but just forgot to mention it.
    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
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    As tabstop points out, all the tentative definitions are taken together (in the absense of an actual definition) to mean (in the singular)
    int x = 0;

    But if there is an actual definition in the code, say
    int x = 1;
    then all the tentative definitions are ignored for the purposes of allocating and initialising some memory.

    Just another one of those little wrinkles which separate C and C++
    http://david.tribble.com/text/cdiffs.htm#C99-odr
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    > with the composite type as of the end of the translation unit, with an initializer
    equal to 0.

    So would this make it a definition, and then it make a multiple definition error?

    http://cboard.cprogramming.com/showp...9&postcount=13

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Global Variables
    By Taka in forum C Programming
    Replies: 34
    Last Post: 11-02-2007, 03:25 AM
  2. Use global variables or pointers?
    By RealityFusion in forum C++ Programming
    Replies: 5
    Last Post: 09-22-2005, 08:47 PM
  3. Replies: 6
    Last Post: 01-02-2004, 01:01 PM
  4. global variables in qbasic
    By Geo-Fry in forum Game Programming
    Replies: 10
    Last Post: 10-09-2003, 07:53 AM
  5. Global Variables - Mutex
    By cjschw in forum C++ Programming
    Replies: 3
    Last Post: 08-16-2003, 06:50 AM