multiple global variable definitions

Discussion in 'C Programming' started by subramanian100in@yahoo.com, India, Mar 19, 2007.

  1. , India

    , India Guest

    Suppose I declare a global variable

    int g;

    in two different files say a.c which has main() and b.c

    When I compile them to build an executable under gcc in Redhat Linux
    with the command

    gcc -std=c99 -pedantic -Wall -Wextra a.c b.c

    there is no linker error.

    I thought there should be linker error because of two definitions for
    the same global variable.

    Where am I going wrong ?
    , India, Mar 19, 2007
    #1
    1. Advertising

  2. <> wrote in message
    news:...
    > Suppose I declare a global variable
    >
    > int g;
    >
    > in two different files say a.c which has main() and b.c
    >
    > When I compile them to build an executable under gcc in Redhat Linux
    > with the command
    >
    > gcc -std=c99 -pedantic -Wall -Wextra a.c b.c
    >
    > there is no linker error.
    >
    > I thought there should be linker error because of two definitions for
    > the same global variable.
    >
    > Where am I going wrong ?
    >

    Global variables declared in the .c file have file scope. You have two
    different variables, the same as declaring the same "int i" as a local
    variable in two different functions. They have the same name, but
    do not overlap in scope.

    There would be only one variable if one file declared the variable to
    be"extern".
    Fred Kleinschmidt, Mar 19, 2007
    #2
    1. Advertising

  3. , India said:

    > Suppose I declare a global variable
    >
    > int g;
    >
    > in two different files say a.c which has main() and b.c
    >
    > When I compile them to build an executable under gcc in Redhat Linux
    > with the command
    >
    > gcc -std=c99 -pedantic -Wall -Wextra a.c b.c
    >
    > there is no linker error.
    >
    > I thought there should be linker error because of two definitions for
    > the same global variable.
    >
    > Where am I going wrong ?


    They are only "tentative" definitions, not actual definitions. There is,
    however, no such thing as a "tentative initialisation", so change them
    both to:

    int g = 0;

    and watch the compiler (or rather the linker) choke.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at the above domain, - www.
    Richard Heathfield, Mar 19, 2007
    #3
  4. Richard Heathfield wrote:
    >, India said:
    >> Suppose I declare a global variable
    >> int g;
    >> in two different files say a.c which has main() and b.c
    >> there is no linker error.
    >>
    >> I thought there should be linker error because of two definitions for
    >> the same global variable.

    >
    >They are only "tentative" definitions, not actual definitions. There is,
    >however, no such thing as a "tentative initialisation", so change them
    >both to:
    >
    >int g = 0;
    >
    >and watch the compiler (or rather the linker) choke.


    Trying to understand the standard, from N1124:

    "6. Language
    ....
    6.9 External Definitions
    ....
    6.9.2 External object definitions
    Semantics
    ....
    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."

    Although I expect the behavior that the OP
    described, the paragraph above seems to contradict
    it:

    int g; "is exactly as" int g = 0;

    What I am missing?

    Also, can somebody clarify the meaning of "with
    the composite type as of the end of the
    translation unit" (I am not sure if I am
    struggling with an unclear text, of with the fact
    that English is not my native language.)

    Roberto Waltman

    [ Please reply to the group,
    return address is invalid ]
    Roberto Waltman, Mar 19, 2007
    #4
  5. , India

    Flash Gordon Guest

    Fred Kleinschmidt wrote, On 19/03/07 14:36:
    > <> wrote in message
    > news:...
    >> Suppose I declare a global variable
    >>
    >> int g;
    >>
    >> in two different files say a.c which has main() and b.c
    >>
    >> When I compile them to build an executable under gcc in Redhat Linux
    >> with the command
    >>
    >> gcc -std=c99 -pedantic -Wall -Wextra a.c b.c
    >>
    >> there is no linker error.
    >>
    >> I thought there should be linker error because of two definitions for
    >> the same global variable.
    >>
    >> Where am I going wrong ?


    Your mistake is assuming that the linker is required to catch your
    error. It isn't.

    > Global variables declared in the .c file have file scope. You have two
    > different variables, the same as declaring the same "int i" as a local
    > variable in two different functions. They have the same name, but
    > do not overlap in scope.
    >
    > There would be only one variable if one file declared the variable to
    > be"extern".


    With neither being declared as extern it invokes undefined behaviour, so
    anything is allowed to happen and the implementation (compiler/linker)
    is not required to generate an error for it. The most common things to
    happen are for the two "int i" definitions to be merged or for an error
    to be generated.
    --
    Flash Gordon
    Flash Gordon, Mar 19, 2007
    #5
  6. , India

    Flash Gordon Guest

    Richard Heathfield wrote, On 19/03/07 15:52:
    > , India said:
    >
    >> Suppose I declare a global variable
    >>
    >> int g;
    >>
    >> in two different files say a.c which has main() and b.c
    >>
    >> When I compile them to build an executable under gcc in Redhat Linux
    >> with the command
    >>
    >> gcc -std=c99 -pedantic -Wall -Wextra a.c b.c
    >>
    >> there is no linker error.
    >>
    >> I thought there should be linker error because of two definitions for
    >> the same global variable.
    >>
    >> Where am I going wrong ?

    >
    > They are only "tentative" definitions, not actual definitions.


    Irrelevant as far as the standard is concerned. As soon as it reaches
    the end of the translation unit it is as if there was a definition with
    an initialiser equal to 2. Section 6.9.2 paragraph 2 of N1124.

    > There is,
    > however, no such thing as a "tentative initialisation", so change them
    > both to:
    >
    > int g = 0;
    >
    > and watch the compiler (or rather the linker) choke.


    It may not since it is undefined behaviour either way. See above and
    section 6.9 paragraph 5.

    To the OP, it does not generate an error because it is not required to.
    It also is not required to "work", it could do anything.

    <OT>
    If using gcc you might want to investigate the -fno-common option.
    </OT>
    --
    Flash Gordon
    Flash Gordon, Mar 19, 2007
    #6
  7. Flash Gordon said:

    > Richard Heathfield wrote, On 19/03/07 15:52:
    >> , India said:
    >>
    >>> Suppose I declare a global variable
    >>>
    >>> int g;
    >>>
    >>> in two different files say a.c which has main() and b.c
    >>>
    >>> When I compile them to build an executable under gcc in Redhat Linux
    >>> with the command
    >>>
    >>> gcc -std=c99 -pedantic -Wall -Wextra a.c b.c
    >>>
    >>> there is no linker error.
    >>>
    >>> I thought there should be linker error because of two definitions
    >>> for the same global variable.
    >>>
    >>> Where am I going wrong ?

    >>
    >> They are only "tentative" definitions, not actual definitions.

    >
    > Irrelevant as far as the standard is concerned.


    I'll take that hit...

    > As soon as it reaches
    > the end of the translation unit it is as if there was a definition
    > with an initialiser equal to 2.


    ....but this puzzles me. Did you mean 0?

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at the above domain, - www.
    Richard Heathfield, Mar 19, 2007
    #7
  8. , India

    Wojtek Lerch Guest

    "Roberto Waltman" <> wrote in message
    news:...
    > Richard Heathfield wrote:
    >>, India said:
    >>> Suppose I declare a global variable
    >>> int g;
    >>> in two different files say a.c which has main() and b.c
    >>> there is no linker error.
    >>>
    >>> I thought there should be linker error because of two definitions for
    >>> the same global variable.


    The C standard doesn't require a linker error if you have two definitions of
    the same global variable. It's undefined behaviour (6.9#5). Whether you
    get an error or not is up to the implementation.

    >>They are only "tentative" definitions, not actual definitions. [...]

    ....
    > Although I expect the behavior that the OP
    > described, the paragraph above seems to contradict
    > it:
    >
    > int g; "is exactly as" int g = 0;
    >
    > What I am missing?


    Nothing. If a translation unit contains a tentative definition, then either
    it also contains a "real" definition, or the behaviour is as if it contained
    a "real" definition. Either way, having two translation units that define
    the same identifier with external linkage (tentatively or otherwise) is
    undefined behaviour.

    > Also, can somebody clarify the meaning of "with
    > the composite type as of the end of the
    > translation unit" (I am not sure if I am
    > struggling with an unclear text, of with the fact
    > that English is not my native language.)


    Consider this translation unit:

    int arr[ 10 ];
    int arr[];

    It contains two tentative definitions that declare "arr" with two different
    types: "int[10]" and "int[]". The composite type is "arr[10]", and
    therefore the behaviour is as if "arr" were defined like this:

    int arr[10] = { 0 };

    rather than like this:

    int arr[] = { 0 };
    Wojtek Lerch, Mar 19, 2007
    #8
  9. On Mon, 19 Mar 2007 17:26:50 +0000, in comp.lang.c , Richard
    Heathfield <> wrote:

    >Flash Gordon said:
    >
    >> As soon as it reaches
    >> the end of the translation unit it is as if there was a definition
    >> with an initialiser equal to 2.

    >
    >...but this puzzles me. Did you mean 0?


    2 would be more entertaining though, don't you think? Shame its not
    allowed...

    --
    Mark McIntyre

    "Debugging is twice as hard as writing the code in the first place.
    Therefore, if you write the code as cleverly as possible, you are,
    by definition, not smart enough to debug it."
    --Brian Kernighan
    Mark McIntyre, Mar 19, 2007
    #9
  10. , India

    Flash Gordon Guest

    Richard Heathfield wrote, On 19/03/07 17:26:
    > Flash Gordon said:
    >
    >> Richard Heathfield wrote, On 19/03/07 15:52:
    >>> , India said:
    >>>
    >>>> Suppose I declare a global variable
    >>>>
    >>>> int g;
    >>>>
    >>>> in two different files say a.c which has main() and b.c
    >>>>
    >>>> When I compile them to build an executable under gcc in Redhat Linux
    >>>> with the command
    >>>>
    >>>> gcc -std=c99 -pedantic -Wall -Wextra a.c b.c
    >>>>
    >>>> there is no linker error.
    >>>>
    >>>> I thought there should be linker error because of two definitions
    >>>> for the same global variable.
    >>>>
    >>>> Where am I going wrong ?
    >>> They are only "tentative" definitions, not actual definitions.

    >> Irrelevant as far as the standard is concerned.

    >
    > I'll take that hit...


    Just goes to show that those claiming you never accept a correction are
    wrong. Something I already knew.

    >> As soon as it reaches
    >> the end of the translation unit it is as if there was a definition
    >> with an initialiser equal to 2.

    >
    > ...but this puzzles me. Did you mean 0?


    Yes, so that's 1 all then :)
    --
    Flash Gordon
    Flash Gordon, Mar 19, 2007
    #10
  11. On Mon, 19 Mar 2007 14:36:43 GMT, "Fred Kleinschmidt"
    <> wrote:

    >
    > <> wrote in message
    > news:...
    > > Suppose I declare a global variable
    > >
    > > int g;
    > >
    > > in two different files say a.c [...] and b.c [...]
    > > there is no linker error.
    > >
    > > I thought there should be linker error because of two definitions for
    > > the same global variable.
    > >
    > > Where am I going wrong ?
    > >

    > Global variables declared in the .c file have file scope. You have two
    > different variables, the same as declaring the same "int i" as a local
    > variable in two different functions. They have the same name, but
    > do not overlap in scope.
    >

    Not really. Each of these is a tentative definition, and assuming
    there is no other definition of the same name (at file scope) with an
    initializer, the tentative definition becomes/produces a (definitive?)
    definition. So you have two t.u.s both defining the same object (name)
    with external linkage, which is Undefined Behavior. The implementation
    is allowed to diagnose this, and in some implementations (and some
    options of some implementations) it does produce a linker error, but
    this is not required, and some don't.

    If you declared/defined it with storage class 'static' in each t.u.,
    then you would (always) have two distinct objects.

    > There would be only one variable if one file declared the variable to
    > be"extern".
    >

    That is the right way to do it, yes. More precisely, one t.u. should
    define it, which is accomplished if you give no storage class, ior if
    you have an initializer (even if you also specify storage class
    'extern'); and the other t.u. (or in general all other t.u.s) should
    declare it with 'extern' and no initializer.
    David Thompson, Apr 15, 2007
    #11
    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. Bryan Parkoff
    Replies:
    2
    Views:
    6,478
  2. Charles L
    Replies:
    5
    Views:
    1,189
    Ron Natalie
    Feb 8, 2005
  3. Panda2
    Replies:
    2
    Views:
    641
  4. Replies:
    9
    Views:
    306
    Flash Gordon
    Mar 5, 2006
  5. Replies:
    8
    Views:
    323
    Mark McIntyre
    Mar 4, 2006
Loading...

Share This Page