473,561 Members | 3,641 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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
Jun 27 '08 #1
11 2905
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
Jun 27 '08 #2
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?
Jun 27 '08 #3
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
Jun 27 '08 #4
In article <2d************ *************** *******@25g2000 hsx.googlegroup s.com>
whirlwindkevin <ma*******@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
Jun 27 '08 #5

"Richard Heathfield" <rj*@see.sig.in validwrote in message
news:fe******** *************** *******@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
Jun 27 '08 #6
"Bartc" <bc@freeuk.comw rites:
"Richard Heathfield" <rj*@see.sig.in validwrote in message
news:fe******** *************** *******@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.
`----

http://publib.boulder.ibm.com/infoce...ative_defn.htm

or

http://tinyurl.com/2fqgx7

In many years of professional programming the issue/word has never come
up for me.
Jun 27 '08 #7
In article <g2**********@r egistered.motza rella.org>,
Richard <rg****@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)
Jun 27 '08 #8
On Mon, 09 Jun 2008 12:12:55 GMT, "Bartc" <bc@freeuk.comw rote in
comp.lang.c:
>
"Richard Heathfield" <rj*@see.sig.in validwrote in message
news:fe******** *************** *******@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++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
Jun 27 '08 #9
whirlwindkevin <ma*******@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
Jun 27 '08 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
2683
by: Senthilraja | last post by:
I have the following program using templates. Someone please let me know the syntax to be used for defining the member functions push, pop etc. as non-inline functions. #include <iostream> using namespace std; template<class T, int size = 50> class Stack {
3
2213
by: Chris Mantoulidis | last post by:
Seperate compilation (that's what it's called, right?) seems to be quite popular, so I decided to get some info about it, and (d'oh) use it... But it's whole structure seems weird to me... Here's what I think of how it is (from what I've read): THE PROJECT +1st header file
9
6630
by: Aguilar, James | last post by:
I know that one can define an essentially unlimited number of classes in a file. And one can declare just as many in a header file. However, the question I have is, should I? Suppose that, to use the common example, I have a situation where I am implementing many types of Shapes. My current way of thinking is, well, since they are all...
1
2218
by: nin234 | last post by:
I tried searching the newgroups for an answer to this question. I found many related topics, but didn't find the exact answer I am looking for. I am implementing a class to aid in the logging for our product as follows. Code snippet is as follows. //Header file srvLog.h starts here
1
3432
by: Arthur Dent | last post by:
Hello all, sorry for the cross-post, but im not sure which group is best for this question. I am an ASP.NET developer, but am learning PHP/perl for the first time now to make some to changes to a client's site which was done by someone else. I wrote a debug TPL which ive got working great now and was Such a sense of accomplishment!! :) ....
2
2969
by: Sike | last post by:
Hi everyone, I've been browsing this and a few other related newsgroups trying to get my head around this problem, and so far all the trails seem to go cold, without an acceptable solution being reached. I'm posting here because there seems to be a few MVP's knocking around, and if they dont know, then it's a safe bet nobody does. I'm...
2
1910
by: Cliff Martin | last post by:
I want to define several groups of related magic numbers. I am writing a program to parse someone else's formatted data, and they have several fields that could be set to a number of different values. Rather than hardcode a number I want to use a text to make it clear what I am comparing to. examples: FieldA 1 foo 2 bar
7
2150
by: Roman Mashak | last post by:
Hello, I have a small piece of code, compiled by two 'gcc' and 'borland builder compiler'. The latter one produces warnings: Public symbol '_freq' defined in both module C:\WRK\ISDB-T\XML\PROBE_XML.OBJ and C:\WRK\ISDB-T\XML\XML.OBJ Public symbol '_power' defined in both module C:\WRK\ISDB-T\XML\PROBE_XML.OBJ and...
2
2652
by: krreks | last post by:
I'm experiencing some (beginner) problems with my header files... I'm writing an message application and want to split my application into multiple files. So far, everything related to bitwise operations is in one, another one contains various other handy functions. Now I want to make a file with the phone and message related functions. In...
0
7648
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7573
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
0
8091
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
1
7620
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
6213
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
1
5473
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
5189
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
1
1184
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
897
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.