Defining variable in C header file related doubt

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • whirlwindkevin

    Defining variable in C header file related doubt

    I saw a program source code in which a variable is defined in a header
    file and that header file is included in 2 different C files.When i
    compile and link the files no error is being thrown.How is this
    possible.I thought it will throw "Variable redefinition Error". Giving
    the source code for reference.Pleas e help me out on this...

    a.h
    -----
    int g;
    void fun(void);

    a.c
    -----
    #include "a.h"
    void main()
    {
    g = 50;
    printf("%d\n",g );
    fun();
    printf("%d\n",g );
    }

    b.c
    ----
    #include "a.h"
    void fun(void)
    {
    g = 120;
    }

    Output is 50...120

    Regards
    Manu
  • Richard Heathfield

    #2
    Re: Defining variable in C header file related doubt

    whirlwindkevin said:
    I saw a program source code in which a variable is defined in a header
    file and that header file is included in 2 different C files.
    And it didn't compile, obviously.
    When i
    compile and link the files no error is being thrown.
    Then you didn't see what you thought you saw.
    How is this
    possible.I thought it will throw "Variable redefinition Error". Giving
    the source code for reference.Pleas e help me out on this...
    >
    a.h
    -----
    int g;
    This is not *exactly* a definition. It's a "tentative definition", and it's
    one of the silliest ideas in C - a silly feature of the language, and
    silly of the programmer to exploit the feature.

    Some terms:
    A *declaration* is you telling the compiler "see this identifier? When I
    use it, I'm talking about an object (or function) of such-and-such a type,
    and just trust me that this object exists, okay?" On that understanding, a
    compiler can go ahead and compile code that can interact even with objects
    or functions that it can't see right now (much as a carpenter can make a
    letterbox in a door even without seeing the actual letters that will drop
    through it, provided you tell him how big the letters will be). But if you
    lie to the compiler, you'll pay later.

    A *definition* is you telling the compiler "make me an object of
    such-and-such a type" (or a "function that does THIS"). If a declaration
    is a promise, then a definition is a way of honouring that promise. A
    definition *is* a declaration (because, when you create an object, that's
    as good a way as any of informing the compiler that the object exists),
    but declarations need not be definitions.

    A "tentative definition" is you telling the compiler "it's my intent to
    create an object of this type, but I'm not really sure whether this is the
    right place to do it". The Standard says:

    "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."

    Best advice? Avoid like the plague. Instead, if you must use file scope
    object identifiers, do it this way:

    1) in exactly one header that can be included by all relevant sources,
    write a declaration, such as:

    extern int IfYouMustDoThis DamnSillyThing;

    2) in the same header, define a sensible initial value for the object:

    #define DO_IT_LIKE_THIS 42

    3) include that header in all relevant sources;

    4) in exactly one source, write a definition at file scope, such as:

    int IfYouMustDoThis DamnSillyThing = DO_IT_LIKE_THIS ;

    void main()
    The main function returns int. If you return anything else from main,
    you're breaking the rules of C, and C is released from any obligation to
    be predictable.

    --
    Richard Heathfield <http://www.cpax.org.uk >
    Email: -http://www. +rjh@
    Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
    "Usenet is a strange place" - dmr 29 July 1999

    Comment

    • whirlwindkevin

      #3
      Re: Defining variable in C header file related doubt

      On Jun 9, 12:27 pm, Richard Heathfield <r...@see.sig.i nvalidwrote:
      whirlwindkevin said:
      >
      I saw a program source code in which a variable is defined in a header
      file and that header file is included in 2 different C files.
      >
      And it didn't compile, obviously.
      >
      When i
      compile and link the files no error is being thrown.
      >
      Then you didn't see what you thought you saw.
      >
      How is this
      possible.I thought it will throw "Variable redefinition Error". Giving
      the source code for reference.Pleas e help me out on this...
      >
      a.h
      -----
      int g;
      >
      This is not *exactly* a definition. It's a "tentative definition", and it's
      one of the silliest ideas in C - a silly feature of the language, and
      silly of the programmer to exploit the feature.
      >
      Some terms:
      A *declaration* is you telling the compiler "see this identifier? When I
      use it, I'm talking about an object (or function) of such-and-such a type,
      and just trust me that this object exists, okay?" On that understanding, a
      compiler can go ahead and compile code that can interact even with objects
      or functions that it can't see right now (much as a carpenter can make a
      letterbox in a door even without seeing the actual letters that will drop
      through it, provided you tell him how big the letters will be). But if you
      lie to the compiler, you'll pay later.
      >
      A *definition* is you telling the compiler "make me an object of
      such-and-such a type" (or a "function that does THIS"). If a declaration
      is a promise, then a definition is a way of honouring that promise. A
      definition *is* a declaration (because, when you create an object, that's
      as good a way as any of informing the compiler that the object exists),
      but declarations need not be definitions.
      >
      A "tentative definition" is you telling the compiler "it's my intent to
      create an object of this type, but I'm not really sure whether this is the
      right place to do it". The Standard says:
      >
      "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."
      >
      Best advice? Avoid like the plague. Instead, if you must use file scope
      object identifiers, do it this way:
      >
      1) in exactly one header that can be included by all relevant sources,
      write a declaration, such as:
      >
      extern int IfYouMustDoThis DamnSillyThing;
      >
      2) in the same header, define a sensible initial value for the object:
      >
      #define DO_IT_LIKE_THIS 42
      >
      3) include that header in all relevant sources;
      >
      4) in exactly one source, write a definition at file scope, such as:
      >
      int IfYouMustDoThis DamnSillyThing = DO_IT_LIKE_THIS ;
      >
      void main()
      >
      The main function returns int. If you return anything else from main,
      you're breaking the rules of C, and C is released from any obligation to
      be predictable.
      >
      --
      Richard Heathfield <http://www.cpax.org.uk >
      Email: -http://www. +rjh@
      Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
      "Usenet is a strange place" - dmr 29 July 1999
      Many Thanks Richard for replying...
      Still i have a doubt related to definition of the variable.Can you
      please tell where variable g (variable in the above program) is
      defined (space is allocated for the variable)? Is it in a.c or is it
      in b.c?

      Comment

      • Richard Heathfield

        #4
        Re: Defining variable in C header file related doubt

        whirlwindkevin said:

        <snip>
        Many Thanks Richard for replying...
        Still i have a doubt related to definition of the variable.Can you
        please tell where variable g (variable in the above program) is
        defined (space is allocated for the variable)? Is it in a.c or is it
        in b.c?
        No, not really. That's partly why it's such a silly idea. Again, I
        recommend that you avoid tentative definitions.

        About the most that can be said is that the compiler, having seen a
        tentative definition, can at least treat it like a declaration - and one
        or other of the tentative definitions is eventually treated as if it were
        a definition.

        --
        Richard Heathfield <http://www.cpax.org.uk >
        Email: -http://www. +rjh@
        Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
        "Usenet is a strange place" - dmr 29 July 1999

        Comment

        • Chris Torek

          #5
          Re: Defining variable in C header file related doubt

          In article <2d761808-e78b-4648-9427-843a7606d01e@25 g2000hsx.google groups.com>
          whirlwindkevin <manumg007@gmai l.comwrote:

          [regarding two separate .c files, both with "int g;" with no
          initializer for either one, that are compiled separately and
          then linked]
          >whirlwindkev in said:
          >>I saw a program source code in which a variable is defined in a header
          >>file and that header file is included in 2 different C files.
          >On Jun 9, 12:27 pm, Richard Heathfield <r...@see.sig.i nvalidwrote:
          >And it didn't compile, obviously.
          Well, actually, it did (for him). But as you note:
          >>int g;
          >>
          >>This is not *exactly* a definition. It's a "tentative definition", and it's
          >>one of the silliest ideas in C - a silly feature of the language, and
          >>silly of the programmer to exploit the feature.
          Tentative definitions are actually useful in a few corner cases,
          such as creating a circularly linked list at compile time that
          has several elements:

          struct foolist {
          struct foolist *next, *prev;
          ... more data here ...
          };

          static struct foolist foo_head, foo_elem_2, foo_tail;

          static struct foo_list foo_head = { &foo_elem_2, &foo_tail, ... };
          static struct foo_list foo_elem_2 = { &foo_tail, &foo_head, ... };
          static struct foo_list foo_tail = { &foo_head, &foo_elem_2, ... };

          In C, you must use tentative definitions to make this work. (For
          non-"static" variables, which have external linkage, you can use
          "extern" to avoid creating tentative definitions.)
          >"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."
          However, as one can see if one has an implementation like the OP's,
          this is not quite true:

          % cat a.define.c
          int x = 0;
          % cat b.define.c
          int x = 0;
          int main(void) { return 0; }
          % cc -o define a.define.c b.define.c
          /tmp/ccodx0za.o(.dat a+0x0): multiple definition of `x'
          /tmp/ccV8U2Fi.o(.dat a+0x0): first defined here
          % cat a.tent.c
          int x;
          % cat b.tent.c
          int x;
          int main(void) { return 0; }
          % cc -o tent a.tent.c b.tent.c
          %

          So, we now have to ask: is this implementation broken? The behavior
          differs for tentative definitions and actual (non-tentative)
          definitions, despite the above quote from the C standard.

          The answer is no, because what the Standard giveth at this point,
          the Standard taketh away elsewhere:

          K.2 Undefined behavior

          [#1] The behavior is undefined in the following circumstances:
          [massive snippage]
          - An identifier with external linkage is used, but in the
          program there does not exist exactly one external definition
          for the identifier, or the identifier is not used and there
          exist multiple external definitions for the identifier.
          (6.7).

          In other words, the implementation can do anything it wants if you
          define the same identifier twice (or any other number of times than
          1 or 0, with "defined 0 times" being OK only for one particular
          case).

          The OP's implementation, like mine above, uses this "undefined
          behavior" license to provide a "feature" of sorts: tentative
          definitions are turned into actual definitions, but not at the end
          of each translation unit. Instead, the compiler waits until the
          last possible moment -- the "link" phase of compilation -- and only
          *then* turns all remaining tentative definitions into actual
          definitions. In the process, it saves a bit of disk space. This
          feature also lets lazy programmers leave out the keyword "extern".
          >Many Thanks Richard for replying...
          >Still i have a doubt related to definition of the variable.Can you
          >please tell where variable g (variable in the above program) is
          >defined (space is allocated for the variable)? Is it in a.c or is it
          >in b.c?
          According to the Standard, it is in both. However, your implementation
          (like mine) makes use of the undefined behavior to cause it to
          happen in *neither*. It happens in a third, "invisible" source
          file that your compiler makes up at the last possible moment. (In
          my implementation, this is not even an actual file at all, although
          some compilers do use an extra file, and even a program called
          "collect2", to handle some tricky cases, particularly when mixing
          C with other languages. If your linker is smart enough, it can
          create a sort of "pretend" file purely in RAM, and avoid the
          "collect2" step. This job is a lot easier for pure C programs; it
          is only those other langauges that create the need for "collect2". )
          --
          In-Real-Life: Chris Torek, Wind River Systems
          Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
          email: gmail (figure it out) http://web.torek.net/torek/index.html

          Comment

          • Bartc

            #6
            Re: Defining variable in C header file related doubt


            "Richard Heathfield" <rjh@see.sig.in validwrote in message
            news:feKdnY5fcr 2nR9HVnZ2dnUVZ8 hednZ2d@bt.com. ..
            whirlwindkevin said:
            >
            >I saw a program source code in which a variable is defined in a header
            >file and that header file is included in 2 different C files.
            >
            And it didn't compile, obviously.
            >
            >When i
            >compile and link the files no error is being thrown.
            >
            Then you didn't see what you thought you saw.
            >
            >How is this
            >possible.I thought it will throw "Variable redefinition Error". Giving
            >the source code for reference.Pleas e help me out on this...
            >>
            >a.h
            >-----
            >int g;
            >
            This is not *exactly* a definition. It's a "tentative definition"
            Looks like an ordinary definition to me. What's tentative about it?

            The OP's question was why, with int g declared in both files (and apparently
            sharing the same space) no error was raised.

            --
            Bartc


            Comment

            • Richard

              #7
              Re: Defining variable in C header file related doubt

              "Bartc" <bc@freeuk.comw rites:
              "Richard Heathfield" <rjh@see.sig.in validwrote in message
              news:feKdnY5fcr 2nR9HVnZ2dnUVZ8 hednZ2d@bt.com. ..
              >whirlwindkev in said:
              >>
              >>I saw a program source code in which a variable is defined in a header
              >>file and that header file is included in 2 different C files.
              >>
              >And it didn't compile, obviously.
              >>
              >>When i
              >>compile and link the files no error is being thrown.
              >>
              >Then you didn't see what you thought you saw.
              >>
              >>How is this
              >>possible.I thought it will throw "Variable redefinition Error". Giving
              >>the source code for reference.Pleas e help me out on this...
              >>>
              >>a.h
              >>-----
              >>int g;
              >>
              >This is not *exactly* a definition. It's a "tentative definition"
              >
              Looks like an ordinary definition to me. What's tentative about it?
              You need to look up the meaning of tentative definition. But you are
              really (in the real world) quite correct. In normal C language it is a
              perfectly normal definition.

              However in language lawyreville:

              ,----
              | A tentative definition is any external data declaration that has no
              | storage class specifier and no initializer. A tentative definition
              | becomes a full definition if the end of the translation unit is reached
              | and no definition has appeared with an initializer for the
              | identifier. In this situation, the compiler reserves uninitialized space
              | for the object defined.
              `----



              or



              In many years of professional programming the issue/word has never come
              up for me.

              Comment

              • Richard Tobin

                #8
                Re: Defining variable in C header file related doubt

                In article <g2j77n$ms9$2@r egistered.motza rella.org>,
                Richard <rgrdev@gmail.c omwrote:
                >>>a.h
                >>>-----
                ;>>>int g;
                >>This is not *exactly* a definition. It's a "tentative definition"
                >Looks like an ordinary definition to me. What's tentative about it?
                >You need to look up the meaning of tentative definition.
                Or he could just have read it, since it was quoted in the article he
                replied to.

                -- Richard
                --
                In the selection of the two characters immediately succeeding the numeral 9,
                consideration shall be given to their replacement by the graphics 10 and 11 to
                facilitate the adoption of the code in the sterling monetary area. (X3.4-1963)

                Comment

                • Jack Klein

                  #9
                  Re: Defining variable in C header file related doubt

                  On Mon, 09 Jun 2008 12:12:55 GMT, "Bartc" <bc@freeuk.comw rote in
                  comp.lang.c:
                  >
                  "Richard Heathfield" <rjh@see.sig.in validwrote in message
                  news:feKdnY5fcr 2nR9HVnZ2dnUVZ8 hednZ2d@bt.com. ..
                  whirlwindkevin said:
                  I saw a program source code in which a variable is defined in a header
                  file and that header file is included in 2 different C files.
                  And it didn't compile, obviously.
                  When i
                  compile and link the files no error is being thrown.
                  Then you didn't see what you thought you saw.
                  How is this
                  possible.I thought it will throw "Variable redefinition Error". Giving
                  the source code for reference.Pleas e help me out on this...
                  >
                  a.h
                  -----
                  int g;
                  This is not *exactly* a definition. It's a "tentative definition"
                  >
                  Looks like an ordinary definition to me. What's tentative about it?
                  >
                  The OP's question was why, with int g declared in both files (and apparently
                  sharing the same space) no error was raised.
                  And the answer is, "C doesn't know or care."

                  The standard states (C99 6.9 p5):

                  "An external def1nition is an external declaration that is also a
                  definition of a function (other than an inline definition) or an
                  object. If an identif1er declared with external linkage is used in an
                  expression (other than as part of the operand of a sizeof operator
                  whose result is an integer constant), somewhere in the entire program
                  there shall be exactly one external definition for the identifier;
                  otherwise, there shall be no more than one."

                  If two translation units that define the same object with external
                  linkage, "int g" in this case, are combined in the same program, the
                  rule above is broken. Since the program violates a "shall" clause
                  outside of a constraints section, the behavior is undefined and no
                  diagnostic is required.

                  Some tool sets will complain about this, others will not. The
                  behavior is undefined either way.

                  --
                  Jack Klein
                  Home: http://JK-Technology.Com
                  FAQs for
                  comp.lang.c http://c-faq.com/
                  comp.lang.c++ http://www.parashift.com/c++-faq-lite/
                  alt.comp.lang.l earn.c-c++

                  Comment

                  • lawrence.jones@siemens.com

                    #10
                    Re: Defining variable in C header file related doubt

                    whirlwindkevin <manumg007@gmai l.comwrote:
                    >
                    I saw a program source code in which a variable is defined in a header
                    file and that header file is included in 2 different C files.When i
                    compile and link the files no error is being thrown.How is this
                    possible.I thought it will throw "Variable redefinition Error". Giving
                    the source code for reference.Pleas e help me out on this...
                    Having multiple definitions results in undefined behavior -- the
                    implementation is not required to diagnose it, and many (if not most)
                    implementations will not, particularly if the definitions are compatible
                    and the variable is not explicitly initialized. The code is still
                    wrong: the header should have only a declaration of the variable (with
                    extern) and exactly one source file should have the actual definition.

                    -- Larry Jones

                    OK, what's the NEXT amendment say? I know it's in here someplace. -- Calvin

                    Comment

                    • James Kuyper

                      #11
                      Re: Defining variable in C header file related doubt

                      Bartc wrote:
                      "Richard Heathfield" <rjh@see.sig.in validwrote in message
                      news:feKdnY5fcr 2nR9HVnZ2dnUVZ8 hednZ2d@bt.com. ..
                      >whirlwindkev in said:
                      ....
                      >>int g;
                      >This is not *exactly* a definition. It's a "tentative definition"
                      >
                      Looks like an ordinary definition to me. What's tentative about it?
                      Other people have told you that it's tentative because the standard
                      defines it to be tentative, and have cited the relevant clause. However,
                      they didn't say why the standard chose the word "tentative" for this
                      purpose.

                      The reason it is tentative is that this definition of 'g' has
                      characteristics that can be changed by a following definition in the
                      same translation unit. If there are no other definitions, then 'g' will
                      have external linkage and be zero-initialized. However, if a following
                      declaration were to say:

                      static int g;

                      Then 'g' would still be tentative, but would have internal linkage.
                      Alternatively, if a following declaration were to say:

                      extern int g;

                      then 'g' would no longer be tentative; it would definitely have external
                      linkage. Note: if different declarations specify both internal and
                      external linkage, then the behavior is undefined. Finally, if as
                      tentative declaration of 'g' were followed by

                      int g = 10;

                      the 'g' would not be zero-initialized; it would be initialized with a
                      value of 10.

                      Comment

                      • manu

                        #12
                        Re: Defining variable in C header file related doubt

                        On Jun 10, 7:00 pm, James Kuyper <jameskuy...@ve rizon.netwrote:
                        Bartc wrote:
                        "Richard Heathfield" <r...@see.sig.i nvalidwrote in message
                        news:feKdnY5fcr 2nR9HVnZ2dnUVZ8 hednZ2d@bt.com. ..
                        whirlwindkevin said:
                        ...
                        >int g;
                        This is not *exactly* a definition. It's a "tentative definition"
                        >
                        Looks like an ordinary definition to me. What's tentative about it?
                        >
                        Other people have told you that it's tentative because the standard
                        defines it to be tentative, and have cited the relevant clause. However,
                        they didn't say why the standard chose the word "tentative" for this
                        purpose.
                        >
                        The reason it is tentative is that this definition of 'g' has
                        characteristics that can be changed by a following definition in the
                        same translation unit. If there are no other definitions, then 'g' will
                        have external linkage and be zero-initialized. However, if a following
                        declaration were to say:
                        >
                        static int g;
                        >
                        Then 'g' would still be tentative, but would have internal linkage.
                        Alternatively, if a following declaration were to say:
                        >
                        extern int g;
                        >
                        then 'g' would no longer be tentative; it would definitely have external
                        linkage. Note: if different declarations specify both internal and
                        external linkage, then the behavior is undefined. Finally, if as
                        tentative declaration of 'g' were followed by
                        >
                        int g = 10;
                        >
                        the 'g' would not be zero-initialized; it would be initialized with a
                        value of 10.
                        Thanks Guys for the help....

                        Comment

                        Working...