extern variable

Discussion in 'C Programming' started by deepak, Aug 7, 2009.

  1. deepak

    deepak Guest

    Here is my program in three different files.

    file1:
    int a;
    char b[10];

    void
    foo(int a)
    {
    printf("\n%d", a);
    }

    file2:

    int a;

    main()
    {
    foo(10);
    printf("\n%d", a);
    }

    file3:

    int a;

    It's compiling and I would like to know for variable 'a' where the
    definition is happening if
    I compile like gcc file1.c file2.c file3.c?

    If extern in missing in second and third file, how it's identifying
    that it's already defined in file1.c

    Please clear my doubt.

    Thanks,
    Deepak
    deepak, Aug 7, 2009
    #1
    1. Advertising

  2. deepak wrote:
    > Here is my program in three different files.
    >
    > file1:
    > int a;
    > char b[10];
    >
    > void
    > foo(int a)
    > {
    > printf("\n%d", a);
    > }
    >
    > file2:
    >
    > int a;
    >
    > main()
    > {
    > foo(10);
    > printf("\n%d", a);
    > }
    >
    > file3:
    >
    > int a;
    >
    > It's compiling and I would like to know for variable 'a' where the
    > definition is happening if
    > I compile like gcc file1.c file2.c file3.c?
    >
    > If extern in missing in second and third file, how it's identifying
    > that it's already defined in file1.c
    >
    > Please clear my doubt.
    >
    > Thanks,
    > Deepak


    In the C language, a variable declared in the global space
    is available to all translation units in the program. The
    "linker" sees that the first file has defined the variable,
    so the other two reference the same variable. It's kind of
    an optimizing thing, to share the same variable. (There
    is a more technical reason, but that lines in the realm of
    the C language standard).

    To have a variable with the same name in multiple translation
    units treated as separate variables, the "static" keyword
    must be used. The "static" keyword says that the variable
    is only known within the translation unit and not to other
    external entities.

    As far as which file actually defines the variable first is
    up to the linker



    --
    Thomas Matthews

    C++ newsgroup welcome message:
    http://www.slack.net/~shiva/welcome.txt
    C++ Faq: http://www.parashift.com/c -faq-lite
    C Faq: http://www.eskimo.com/~scs/c-faq/top.html
    alt.comp.lang.learn.c-c++ faq:
    http://www.comeaucomputing.com/learn/faq/
    Other sites:
    http://www.josuttis.com -- C++ STL Library book
    http://www.sgi.com/tech/stl -- Standard Template Library
    Thomas Matthews, Aug 7, 2009
    #2
    1. Advertising

  3. deepak

    Richard Bos Guest

    deepak <> wrote:

    > Here is my program in three different files.


    [ Snipping everything that isn't relevant... ]

    > file1:
    > int a;


    > file2:
    >
    > int a;


    > file3:
    >
    > int a;


    > It's compiling and I would like to know for variable 'a' where the
    > definition is happening if
    > I compile like gcc file1.c file2.c file3.c?


    Wherever gcc likes to put it.

    In theory, this may even be nowhere, because your program has undefined
    behaviour. According to 6.9.2, all three declarations of a are also
    tentative definitions, and (there being no others in their respective
    translation units) end up as external definitions. But according to
    6.9#5, there shall only be one of those. You have three. Hence, you
    break a "shall" that is outside a constraint; hence, you have undefined
    behaviour.
    As I wrote: in theory. In practice, gcc probably solves this by
    noticing, during its linking stage, that it has collected three a's in
    its public symbol table and they all have the same type, so it creates
    one object with that type for all three of those identifiers to refer
    to. That's how I would do it, except that I would print a warning
    message, as well.
    Goodness knows where it leaves that object, though. But you should not
    need to care. All you should need to know is that if you correct your
    code, a has external linkage (i.e., all a's refer to the same object);
    it has static duration (i.e., that object is created just before your
    main function starts and isn't destroyed until after your last atexit()
    function ends); and since you didn't explicitly initialise this static
    object, it is automatically initialised to 0; and finally, that it is
    highly likely, even if not guaranteed, that this is the case even in
    your broken case.

    > If extern in missing in second and third file, how it's identifying
    > that it's already defined in file1.c


    Again: however it likes to. It is not required to by the Standard, but
    it is allowed to apply whatever internal compiler magic it likes. And
    again, you should not even care how: what you should do is put those
    externs back where they belong. And, I suspect, increase the warning
    level on your compiles.

    Richard
    Richard Bos, Aug 7, 2009
    #3
  4. On Fri, 07 Aug 2009 16:03:39 GMT, (Richard Bos)
    wrote:

    > deepak <> wrote:

    <snip: three t.u.s each with int a;>

    > In theory, this may even be nowhere, because your program has undefined
    > behaviour. According to 6.9.2, all three declarations of a are also
    > tentative definitions, and (there being no others in their respective
    > translation units) end up as external definitions. But according to
    > 6.9#5, there shall only be one of those. You have three. Hence, you
    > break a "shall" that is outside a constraint; hence, you have undefined
    > behaviour.


    Right.

    > As I wrote: in theory. In practice, gcc probably solves this by
    > noticing, during its linking stage, that it has collected three a's in
    > its public symbol table and they all have the same type, so it creates
    > one object with that type for all three of those identifiers to refer
    > to. That's how I would do it, except that I would print a warning
    > message, as well.


    People sometimes use gcc to mean just the compiler(s?), and
    sometimes the driver which runs the whole sequence including linking.
    But the linking 'stage' as you call it is always a separate program.
    On some platforms/targets, the linker is from another GNU package
    'binutils' and we can still make useful statements about it from the
    GNU doc (although not strictly the gcc part), but on some platforms
    gcc uses the 'native' linker. In particular, GNU ld is (I think
    always) and other linkers _may_ be affected by whether (the compiler
    actually invoked under) gcc marks items in the object files as
    'common'; this can be controlled by -f[no-]common.

    The traditional behavior for common is to take the largest size
    specified by any object file = t.u., and (initial) contents specified
    by some object file that does so if any do. I.e. if all files leave
    the contents default = zero-bits, that is used; if only one file has
    contents, those are used; if more than one file has contents, one of
    them is used, but which one might vary depending on the linker.
    AFAIK GNU ld always does this for common, and other linkers if they
    have common at all are reasonably likely to do so. Object files
    typically don't represent type in a fashion understood by the linker,
    only size; and even size differences aren't usually treated as an
    error because this capability was originally designed to handle COMMON
    in FORTRAN, hence the name, which does allow some size differences.

    GNU ld gives an error if multiple t.u.s have no-common definitions.
    Other linkers may vary rather more in this mode.

    Similar principles apply to many (probably all) other compilers also,
    but the details vary.

    > Goodness knows where it leaves that object, though. But you should not
    > need to care. All you should need to know is that if you correct your
    > code, a has external linkage (i.e., all a's refer to the same object);
    > it has static duration (i.e., that object is created just before your
    > main function starts and isn't destroyed until after your last atexit()
    > function ends); and since you didn't explicitly initialise this static
    > object, it is automatically initialised to 0; and finally, that it is
    > highly likely, even if not guaranteed, that this is the case even in
    > your broken case.
    >

    Agree with all of those. And add that you may not know, and shouldn't
    care, where the linker puts an object even when it's coded correctly:
    one definition and other nondefining references; or no references.
    David Thompson, Aug 17, 2009
    #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,369
    tom_usenet
    Aug 2, 2004
  2. Dan Elliott
    Replies:
    4
    Views:
    13,231
    Tom Widmer
    Dec 8, 2004
  3. smackdab

    extern access to variable

    smackdab, Dec 8, 2003, in forum: C Programming
    Replies:
    1
    Views:
    439
    Jack Klein
    Dec 8, 2003
  4. Bangalore

    extern struct variable

    Bangalore, Aug 2, 2005, in forum: C++
    Replies:
    5
    Views:
    431
    Srini
    Sep 6, 2005
  5. Andre
    Replies:
    5
    Views:
    517
    Keith Thompson
    Jul 17, 2012
Loading...

Share This Page