declare vs define of global variables

Discussion in 'C Programming' started by Brian Sammon, Oct 5, 2004.

  1. Brian Sammon

    Brian Sammon Guest

    According to my programming textbook, "int a;" at the top level of a
    file is a definition which shouldn't go in a header file.
    However, I'm running into a lot of online documentation that treats that
    kind of statement as a declaration that can be in a header file used in
    multiple compilation units.
    Which of these is correct? Is this something that has changed between
    different standards?
     
    Brian Sammon, Oct 5, 2004
    #1
    1. Advertising

  2. Brian Sammon

    Jack Klein Guest

    On Mon, 4 Oct 2004 22:41:52 -0400, Brian Sammon
    <> wrote in comp.lang.c:

    > According to my programming textbook, "int a;" at the top level of a
    > file is a definition which shouldn't go in a header file.
    > However, I'm running into a lot of online documentation that treats that
    > kind of statement as a declaration that can be in a header file used in
    > multiple compilation units.
    > Which of these is correct? Is this something that has changed between
    > different standards?



    What kind of online documentation? What reason do you have to trust
    its quality? If this documentation talks about using a declaration
    like:

    int a;

    ....without either the 'static' or 'extern' keywords at file scope, the
    documentation is just plain wrong, and nothing has changed in
    different versions of the C standard in this regard.

    At file scope a definition like:

    int a; /* no initializer */

    ....is called a 'tentative definition'. The identifier 'a' is declared
    with file scope to have static storage duration, int type, and
    external linkage. There may be more than one tentative definition for
    the same identifier at file scope, as long as they all apply to the
    same object type:

    When there is a tentative definition in the file, one of two things
    happens.

    1. There is a later definition with an initializer (called an
    'external definition'):

    int a = 42;

    2. There is no external definition, that is file scope declaration
    with an initializer. In this case, at the end of the translation
    unit, the compiler will act as though an external definition with an
    initializer of 0 existed.

    According to the C standard, you produce undefined behavior and C
    takes no responsibility for the results by defining an object with
    external linkage in multiple translation units. The standard states
    that for each external object that is actually referenced in a
    program, there must be exactly one definition.

    It just so happens that there are some compiler/linker combinations
    that allow this, as long as no more than one source file contains an
    initializer for the object. It also happens that there are other
    compiler/linker combinations that will reject the program even if none
    of the source files contains an initializer.

    In any case, it is specifically invalid and non-portable.

    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
    comp.lang.c++ http://www.parashift.com/c -faq-lite/
    alt.comp.lang.learn.c-c++
    http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
     
    Jack Klein, Oct 5, 2004
    #2
    1. Advertising

  3. On Mon, 4 Oct 2004 22:41:52 -0400, Brian Sammon
    <> had a scratch and wrote:

    >According to my programming textbook, "int a;" at the top level of a
    >file is a definition which shouldn't go in a header file.
    >However, I'm running into a lot of online documentation that treats that
    >kind of statement as a declaration that can be in a header file used in
    >multiple compilation units.
    >Which of these is correct? Is this something that has changed between
    >different standards?



    extern int a; /* an allusion to a - it tells the compiler to look
    elsewhere for the definition - that's what you'd expect in a header
    file *./

    int a; /* a tentative definition or an allusion - it's up to the
    compiler to decide on the basis of what's elsewhere in the source file
    */

    int a=0; /* a real definition */


    ANSI, K&R, and Unix all have different strategies for resolving
    tentative definitions, allusions, and real declarations.




    =====================



    Pussie sHaveMo
    reFunMeow MeowMeowPus
    siesHaveMore FunMeowMeowMeo
    wPussiesHaveMo reFunMeowMeowMeo
    wPussiesHaveMor eFunMeowMeowMeowP
    ussiesHaveMoreFu nMeowMeowMeowPussi
    esHaveMoreFunMeo wMeowMeowPussiesHav
    eMoreFunMeowMeowM eowPussiesHaveMor
    eFunMeowMeowMeowP ussiesHaveMoreFunM
    eowMeowMeowPussie sHaveMoreFunMeowMe owMeowPus
    siesHaveM oreFunMeowMeowMe owPussiesHaveMore FunMeowMeowMe
    owPussiesHave MoreFunMeowMeowM eowPussiesHaveM oreFunMeowMeowM
    eowPussiesHaveM oreFunMeowMeow MeowPussiesHa veMoreFunMeowMeow
    MeowPussiesHave MoreFunMeow MeowMeow PussiesHaveMoreFun
    MeowMeowMeowPussi esHa veMoreFunMeowMeowMe
    owPussiesHaveMoreF unMeowMeowM eowPussiesHaveMoreFu
    nMeowMeowMeowPussie sHaveMoreFunMe owMeowMeowPussiesHav
    eMoreFunMeowMeowMeo wPussiesHaveMoreFu nMeowMeowMeowPussie
    sHaveMoreFunMeowMeo wMeowPussiesHaveMoreFu nMeowMeowMeowPussi
    esHaveMoreFunMeowM eowMeowPussiesHaveMoreFu nMeowMeowMeowPuss
    iesHaveMoreFunMe owMeowMeowPussiesHaveMoreFu nMeowMeowMeowP
    ussiesHaveMor eFunMeowMeowMeowPussiesHaveMore FunMeowMeow
    MeowPussi esHaveMoreFunMeowMeowMeowPussiesHave MoreF
    unMe owMeowM eowPuss
    iesHave MoreF unMeowMeowM
    eowPussies Ha veMoreFunMeo
    wMeowMeowP us si esHaveMoreFu
    nMeowMeowM eow Pus siesHaveMore
    FunMeowMeo wMeow Pussi esHaveMoreFu
    nMeowMeow MeowPu ssiesH aveMoreFun
    Meow MeowMeow Pussie
    sHaveMoreFunMeowMeowMeowPussiesHaveM
    oreFunMeowMeowMeowPussiesHaveMo
    reFunMeowMeowMeowPussies
     
    Bradley Bungmunch, Oct 7, 2004
    #3
  4. On Mon, 04 Oct 2004 22:19:10 -0500, Jack Klein <>
    had a scratch and wrote:

    >On Mon, 4 Oct 2004 22:41:52 -0400, Brian Sammon
    ><> wrote in comp.lang.c:
    >
    >> According to my programming textbook, "int a;" at the top level of a
    >> file is a definition which shouldn't go in a header file.
    >> However, I'm running into a lot of online documentation that treats that
    >> kind of statement as a declaration that can be in a header file used in
    >> multiple compilation units.
    >> Which of these is correct? Is this something that has changed between
    >> different standards?

    >
    >
    >What kind of online documentation? What reason do you have to trust
    >its quality? If this documentation talks about using a declaration
    >like:
    >
    > int a;
    >
    >...without either the 'static' or 'extern' keywords at file scope, the
    >documentation is just plain wrong, and nothing has changed in
    >different versions of the C standard in this regard.
    >
    >At file scope a definition like:
    >
    > int a; /* no initializer */
    >
    >...is called a 'tentative definition'. The identifier 'a' is declared
    >with file scope to have static storage duration, int type, and
    >external linkage. There may be more than one tentative definition for
    >the same identifier at file scope, as long as they all apply to the
    >same object type:
    >
    >When there is a tentative definition in the file, one of two things
    >happens.
    >
    >1. There is a later definition with an initializer (called an
    >'external definition'):
    >
    > int a = 42;
    >
    >2. There is no external definition, that is file scope declaration
    >with an initializer. In this case, at the end of the translation
    >unit, the compiler will act as though an external definition with an
    >initializer of 0 existed.
    >
    >According to the C standard, you produce undefined behavior and C
    >takes no responsibility for the results by defining an object with
    >external linkage in multiple translation units. The standard states
    >that for each external object that is actually referenced in a
    >program, there must be exactly one definition.
    >
    >It just so happens that there are some compiler/linker combinations
    >that allow this, as long as no more than one source file contains an
    >initializer for the object.
    >

    A but it's a little bit more complex than that. K&R C says if you put
    extern first then the presence or absence of an initializer makes no
    difference - it's always an allusion.


    > It also happens that there are other
    >compiler/linker combinations that will reject the program even if none
    >of the source files contains an initializer.
    >
    >In any case, it is specifically invalid and non-portable.



    =====================



    Pussie sHaveMo
    reFunMeow MeowMeowPus
    siesHaveMore FunMeowMeowMeo
    wPussiesHaveMo reFunMeowMeowMeo
    wPussiesHaveMor eFunMeowMeowMeowP
    ussiesHaveMoreFu nMeowMeowMeowPussi
    esHaveMoreFunMeo wMeowMeowPussiesHav
    eMoreFunMeowMeowM eowPussiesHaveMor
    eFunMeowMeowMeowP ussiesHaveMoreFunM
    eowMeowMeowPussie sHaveMoreFunMeowMe owMeowPus
    siesHaveM oreFunMeowMeowMe owPussiesHaveMore FunMeowMeowMe
    owPussiesHave MoreFunMeowMeowM eowPussiesHaveM oreFunMeowMeowM
    eowPussiesHaveM oreFunMeowMeow MeowPussiesHa veMoreFunMeowMeow
    MeowPussiesHave MoreFunMeow MeowMeow PussiesHaveMoreFun
    MeowMeowMeowPussi esHa veMoreFunMeowMeowMe
    owPussiesHaveMoreF unMeowMeowM eowPussiesHaveMoreFu
    nMeowMeowMeowPussie sHaveMoreFunMe owMeowMeowPussiesHav
    eMoreFunMeowMeowMeo wPussiesHaveMoreFu nMeowMeowMeowPussie
    sHaveMoreFunMeowMeo wMeowPussiesHaveMoreFu nMeowMeowMeowPussi
    esHaveMoreFunMeowM eowMeowPussiesHaveMoreFu nMeowMeowMeowPuss
    iesHaveMoreFunMe owMeowMeowPussiesHaveMoreFu nMeowMeowMeowP
    ussiesHaveMor eFunMeowMeowMeowPussiesHaveMore FunMeowMeow
    MeowPussi esHaveMoreFunMeowMeowMeowPussiesHave MoreF
    unMe owMeowM eowPuss
    iesHave MoreF unMeowMeowM
    eowPussies Ha veMoreFunMeo
    wMeowMeowP us si esHaveMoreFu
    nMeowMeowM eow Pus siesHaveMore
    FunMeowMeo wMeow Pussi esHaveMoreFu
    nMeowMeow MeowPu ssiesH aveMoreFun
    Meow MeowMeow Pussie
    sHaveMoreFunMeowMeowMeowPussiesHaveM
    oreFunMeowMeowMeowPussiesHaveMo
    reFunMeowMeowMeowPussies
     
    Bradley Bungmunch, Oct 7, 2004
    #4
  5. In article <>,
    Bradley Bungmunch < > wrote:

    >extern int a; /* an allusion to a - it tells the compiler to look
    >elsewhere for the definition - that's what you'd expect in a header
    >file *./


    Note that that "elsewhere" might be later in the file (but, for a header,
    shouldn't be).


    >int a; /* a tentative definition or an allusion - it's up to the
    >compiler to decide on the basis of what's elsewhere in the source file
    >*/


    The "what's elsewhere in the source file" (translation unit, to be
    precise) here is fairly straightforward: If there's no "true" definition
    (one that actually allocates storage), this becomes one, otherwise
    it doesn't.


    >int a=0; /* a real definition */
    >
    >
    >ANSI, K&R, and Unix all have different strategies for resolving
    >tentative definitions, allusions, and real declarations.


    C requires that there be at most one "true" definition for each
    identifier; having more than one in the same translation unit is
    a constraint violation, and having more than one across different
    translation units invokes undefined behavior.

    Some implementations handle this particular type of undefined behavior
    by reporting an error at link time; others silently ignore multiple
    definitions and treat them as simply references to the same object (which
    makes things work as expected if they're the same type, and introduces
    Interesting errors otherwise); others can have more creative ways of
    dealing with this.



    [snip 40 lines]

    Isn't alt.fan.warlord the appropriate newsgroup to crosspost to with
    oversized .sigs?


    dave

    --
    Dave Vandervies
    Maybe I should add a line that says, "No matter what you do, it is sure
    to annoy at least one of the regulars".
    --Billy Chambless in comp.lang.c
     
    Dave Vandervies, Oct 7, 2004
    #5
  6. Brian Sammon

    Old Wolf Guest

    Jack Klein <> wrote:
    >
    > int a;
    >
    > ...without either the 'static' or 'extern' keywords at file scope, the
    > documentation is just plain wrong, and nothing has changed in
    > different versions of the C standard in this regard.


    I'm not sure what you mean by "plain wrong". The rest of
    your message explains how it is a tentative definition
    (which is surely a correct usage). Of course it is wrong
    to have 2 different objects with external linkage but the same
    name.

    I use this in my code sometimes:
    STATIC int a;
    the point being that if the object has internal linkage then
    it doesn't show up in the map file and I don't know its address
    so I can't inspect it in the (non-integrated) debugger.
    So I can define STATIC as nothing while debugging, and then
    define it as 'static' for the release version.
    Of course I attempt to choose more unique names than 'a'.

    > 2. There is no external definition, that is file scope declaration
    > with an initializer. In this case, at the end of the translation
    > unit, the compiler will act as though an external definition with an
    > initializer of 0 existed.


    Unfortunately I've encountered many (non-standard of course)
    embedded compilers that don't initialize the variable to 0.
    Does this match your experience?
    (I'm now in the habit of specifically initializing all my
    file-scope variables, then the linker puts them in a different
    section and they get initialized correctly).
     
    Old Wolf, Oct 7, 2004
    #6
  7. Brian Sammon

    Mabden Guest

    "Old Wolf" <> wrote in message
    news:...
    > Of course I attempt to choose more unique names than 'a'.


    But..., doesn't that make your code easier to understand?

    > (I'm now in the habit of specifically initializing all my
    > file-scope variables, then the linker puts them in a different
    > section and they get initialized correctly).


    But..., don't you lose the "Surprise!" factor?

    It all sounds very planned out and boring...

    --
    Mabden
     
    Mabden, Oct 7, 2004
    #7
  8. Brian Sammon

    Flash Gordon Guest

    On 7 Oct 2004 14:55:28 -0700
    (Old Wolf) wrote:

    > Jack Klein <> wrote:
    > >
    > > int a;
    > >
    > > ...without either the 'static' or 'extern' keywords at file scope,
    > > the documentation is just plain wrong, and nothing has changed in
    > > different versions of the C standard in this regard.

    >
    > I'm not sure what you mean by "plain wrong". The rest of
    > your message explains how it is a tentative definition
    > (which is surely a correct usage). Of course it is wrong
    > to have 2 different objects with external linkage but the same
    > name.
    >
    > I use this in my code sometimes:
    > STATIC int a;
    > the point being that if the object has internal linkage then
    > it doesn't show up in the map file and I don't know its address
    > so I can't inspect it in the (non-integrated) debugger.
    > So I can define STATIC as nothing while debugging, and then
    > define it as 'static' for the release version.
    > Of course I attempt to choose more unique names than 'a'.


    You need a better debugger. Most of the debuggers I've used with In
    Circuit Emulators and simulators could cope with static and local
    variable. Of course, you probably don't have any choice in debuggers :-(

    > > 2. There is no external definition, that is file scope declaration
    > > with an initializer. In this case, at the end of the translation
    > > unit, the compiler will act as though an external definition with an
    > > initializer of 0 existed.

    >
    > Unfortunately I've encountered many (non-standard of course)
    > embedded compilers that don't initialize the variable to 0.
    > Does this match your experience?
    > (I'm now in the habit of specifically initializing all my
    > file-scope variables, then the linker puts them in a different
    > section and they get initialized correctly).


    I've had this problem as well. My solution was to reset all memory to
    all bits zero during a RAM test that was done at power up in the
    startup code (i.e. as part of initialising the C environment).
    --
    Flash Gordon
    Sometimes I think shooting would be far too good for some people.
    Although my email address says spam, it is real and I read it.
     
    Flash Gordon, Oct 8, 2004
    #8
    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. David T. Ashley
    Replies:
    6
    Views:
    545
    Tim Rentsch
    Dec 5, 2004
  2. David T. Ashley
    Replies:
    6
    Views:
    390
    Tim Rentsch
    Dec 5, 2004
  3. G Iveco
    Replies:
    6
    Views:
    501
    Mike Treseler
    Aug 7, 2007
  4. rick
    Replies:
    4
    Views:
    156
    Michael Winter
    Apr 19, 2004
  5. yoodavid
    Replies:
    64
    Views:
    603
    Tim Rentsch
    Oct 24, 2013
Loading...

Share This Page