extern variable

D

deepak

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
 
T

Thomas Matthews

deepak said:
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
 
R

Richard Bos

deepak said:
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
 
D

David Thompson

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top