Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > linking problem? | extern keyword

Reply
Thread Tools

linking problem? | extern keyword

 
 
Stanley Rice
Guest
Posts: n/a
 
      11-14-2011
Dear all

I got a question about the key word 'extern', In f1.c, I define a
variable as below:
--------------f1.c--------------
float var = 3.0F;

but in file main.c, I declare it as type double
---------------main.c-------------
extern double var;
......
printf("%f\n", var);
.....

At first, I guess that the compiler(gcc) will shout to me, as 'var' in
f1.c is defined in type float, but I declare the var in main.c with
type double, which is inconsistant. However, the compiler happily
accept it. But the result isn't what I expect. It prints 0.000000
instead of 3.0, and I couldn't find the reason here.

For another try, I define a variable as below:
--------------f2.c------------------
unsigned int var_int = 4;

in another file, say, main.c, I declare it as below
-------------main.c----------------
extern int var_int;
.....
printf("%d\n", var_int);

This time, define var_int in type 'unsigned int' but declare it in
type 'int' in another file, the printed result is 4, which is
consistant with what it is previously defined.

Could anyone what happens? why doesn't the compiler complains, and why
the two results differs. Thanks in advance.
 
Reply With Quote
 
 
 
 
Ike Naar
Guest
Posts: n/a
 
      11-14-2011
On 2011-11-14, Stanley Rice <(E-Mail Removed)> wrote:
> I got a question about the key word 'extern', In f1.c, I define a
> variable as below:
> --------------f1.c--------------
> float var = 3.0F;
>
> but in file main.c, I declare it as type double
> ---------------main.c-------------
> extern double var;
> .....
> printf("%f\n", var);
> ....
>
> At first, I guess that the compiler(gcc) will shout to me, as 'var' in
> f1.c is defined in type float, but I declare the var in main.c with
> type double, which is inconsistant. However, the compiler happily
> accept it. But the result isn't what I expect. It prints 0.000000
> instead of 3.0, and I couldn't find the reason here.


The usual way to solve this problem is to use a header file,
say f1.h, that contains the external declarations of f1.c .

/* f1.h */
extern float var;

Then #include f1.h in f1.c and in every file that uses var.
So, in main.c, instead of having

extern double var;

use

#include "f1.h"
 
Reply With Quote
 
 
 
 
Jens Thoms Toerring
Guest
Posts: n/a
 
      11-14-2011
Stanley Rice <(E-Mail Removed)> wrote:
> Dear all


> I got a question about the key word 'extern', In f1.c, I define a
> variable as below:
> --------------f1.c--------------
> float var = 3.0F;


> but in file main.c, I declare it as type double
> ---------------main.c-------------
> extern double var;
> .....
> printf("%f\n", var);
> ....


> At first, I guess that the compiler(gcc) will shout to me, as 'var' in
> f1.c is defined in type float, but I declare the var in main.c with
> type double, which is inconsistant. However, the compiler happily
> accept it.


That was to be expected. When the compiler compiles main.c
it has no idea what is in f1.c and vice versa. Remember,
the compiler is always working on a single C file and it
has to trust you if you tell it that you defined a vari-
able in another file and that it has the correct type.

> But the result isn't what I expect. It prints 0.000000
> instead of 3.0, and I couldn't find the reason here.


Well, when the compiler is finished the linker got to work
out things. And the compiler tells the linker that for
main.o it needs a variable with the name 'var' from some-
where else, but it doesn't tell the linker about the type,
that's something you must have gotten right. And since the
linker finds a variable named 'var' it's quite happy and
also can't detect this error. But when the program finally
is run it will try to access 'var' in main.c as a double
despite it being only a float. The result is anyones guess
since the sizes of float and double are rather likely to
be different as are their bit representations.

> For another try, I define a variable as below:
> --------------f2.c------------------
> unsigned int var_int = 4;


> in another file, say, main.c, I declare it as below
> -------------main.c----------------
> extern int var_int;
> ....
> printf("%d\n", var_int);


> This time, define var_int in type 'unsigned int' but declare it in
> type 'int' in another file, the printed result is 4, which is
> consistant with what it is previously defined.


Here's the same problem but since 'int' and 'unsigned int'
have the same size and more or less the same bit represen-
tation (i.e. if you compare the bit pattern for an int set
to 4 and that of an unsigned int, also set to 4 they will
be the same) you just get away with it

If you would have done it the other way round, i.e define
'var' as an int and set it to a negative value and then
declare 'var' in main.c as unsigned int you would have
gotten some strange number printed out.

> Could anyone what happens? why doesn't the compiler complains, and why
> the two results differs. Thanks in advance.


The compiler can't complain because it doesn't know any-
thing about the "real" 'var' variable while its com-
piling main.c (if it would know about it the 'extern'
declaration would be rather redundant). And this leads
to your program using a float variable as if it were a
double, which it isn't.
Regards, Jens
--
\ Jens Thoms Toerring ___ http://www.velocityreviews.com/forums/(E-Mail Removed)
\__________________________ http://toerring.de
 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      11-14-2011
On 11/14/2011 07:20 AM, Stanley Rice wrote:
> Dear all
>
> I got a question about the key word 'extern', In f1.c, I define a
> variable as below:
> --------------f1.c--------------
> float var = 3.0F;
>
> but in file main.c, I declare it as type double
> ---------------main.c-------------
> extern double var;
> .....
> printf("%f\n", var);
> ....
>
> At first, I guess that the compiler(gcc) will shout to me, as 'var' in
> f1.c is defined in type float, but I declare the var in main.c with
> type double, which is inconsistant. However, the compiler happily
> accept it. But the result isn't what I expect. It prints 0.000000
> instead of 3.0, and I couldn't find the reason here.


The reason is that such a mis-match makes the behavior of your program
undefined. When you have separate compile-link phases, it's not possible
for the compiler to notice this discrepancy, it doesn't have enough
information. In principle, a linker could generate such a message, but
the C standard does not require it, and most will not provide one.

> For another try, I define a variable as below:
> --------------f2.c------------------
> unsigned int var_int = 4;
>
> in another file, say, main.c, I declare it as below
> -------------main.c----------------
> extern int var_int;
> ....
> printf("%d\n", var_int);
>
> This time, define var_int in type 'unsigned int' but declare it in
> type 'int' in another file, the printed result is 4, which is
> consistant with what it is previously defined.
>
> Could anyone what happens? why doesn't the compiler complains, and why
> the two results differs. Thanks in advance.


In principle, the behavior is just as undefined in this case as in the
other. However, when the behavior is undefined, that means that anything
is permitted by the C standard, including having the program do exactly
what you incorrectly thought it was required to do. In this case, since
the C standard mandates that positive integer values have exactly the
same representation in the corresponding unsigned type, it is very
likely to work on most implementations. No such requirement applied in
the double/float case.
--
James Kuyper
 
Reply With Quote
 
Quentin Carbonneaux
Guest
Posts: n/a
 
      11-14-2011
On 2011-11-14, Stanley Rice <(E-Mail Removed)> wrote:
> Dear all
>
> I got a question about the key word 'extern', In f1.c, I define a
> variable as below:
> --------------f1.c--------------
> float var = 3.0F;
>
> but in file main.c, I declare it as type double
> ---------------main.c-------------
> extern double var;
> .....
> printf("%f\n", var);
> ....
>
> At first, I guess that the compiler(gcc) will shout to me, as 'var' in
> f1.c is defined in type float, but I declare the var in main.c with
> type double, which is inconsistant. However, the compiler happily
> accept it. But the result isn't what I expect. It prints 0.000000
> instead of 3.0, and I couldn't find the reason here.


For the sake of separate compilation no tests are done regarding
interfaces during linkage of the separate objects of your program.

The behavior of your program is unspecified as stated in the standard
(6.2.7p2):

All declarations that refer to the same object shall have compatible
type; otherwise, the behavior is undefined.

Thus, it is no use to interpret the results of your program.

--
qcar
 
Reply With Quote
 
Stanley Rice
Guest
Posts: n/a
 
      11-15-2011
On Nov 14, 8:52*pm, Ike Naar <(E-Mail Removed)> wrote:
> On 2011-11-14, Stanley Rice <(E-Mail Removed)> wrote:
>
>
>
>
>
>
>
>
>
> > I got a question about the key word 'extern', In f1.c, I define a
> > variable as below:
> > --------------f1.c--------------
> > float var = 3.0F;

>
> > but in file main.c, I declare it as type double
> > ---------------main.c-------------
> > extern double var;
> > .....
> > printf("%f\n", var);
> > ....

>
> > At first, I guess that the compiler(gcc) will shout to me, as 'var' in
> > f1.c is defined in type float, but I declare the var in main.c with
> > type double, which is inconsistant. However, the compiler happily
> > accept it. But the result isn't what I expect. It prints 0.000000
> > instead of 3.0, and I couldn't find the reason here.

>
> The usual way to solve this problem is to use a header file,
> say f1.h, that contains the external declarations of f1.c .
>
> /* f1.h */
> extern float var;
>
> Then #include f1.h in f1.c and in every file that uses var.
> So, in main.c, instead of having
>
> * extern double var;
>
> use
>
> * #include "f1.h"


Yeah, you are right. And I know how to solve the problem as you said
above. Here I declare 'var' deliberately in type double, and want to
know why the compiler happily accept it and how it works.
 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      11-15-2011
On 11/15/2011 12:42 AM, Stanley Rice wrote:
> On Nov 14, 8:52�pm, Ike Naar <(E-Mail Removed)> wrote:
>> On 2011-11-14, Stanley Rice <(E-Mail Removed)> wrote:

....
>>> I got a question about the key word 'extern', In f1.c, I define a
>>> variable as below:
>>> --------------f1.c--------------
>>> float var = 3.0F;

>>
>>> but in file main.c, I declare it as type double
>>> ---------------main.c-------------
>>> extern double var;
>>> .....
>>> printf("%f\n", var);
>>> ....

>>
>>> At first, I guess that the compiler(gcc) will shout to me, as 'var' in
>>> f1.c is defined in type float, but I declare the var in main.c with
>>> type double, which is inconsistant. However, the compiler happily
>>> accept it. But the result isn't what I expect. It prints 0.000000
>>> instead of 3.0, and I couldn't find the reason here.

....
> Yeah, you are right. And I know how to solve the problem as you said
> above. Here I declare 'var' deliberately in type double, and want to
> know why the compiler happily accept it and how it works.


I thought that your question had already been answered, but you wrote
"want to know" in the present tense, implying that you're still looking
for something more than the answers you've already received. Here's
another explanation, I hope it may help:

The compiler happily accepts your modules because it never sees the
discrepancy; it only sees f1.c, or main.c; it never looks at both at the
same time. That's why the solution is to put the declaration in a header
file that is shared by both translation units.

The linker could have enough information to detect the problem, if the
object file format permits the storage of the relevant information, and
if the compiler provides it. However, such information is not needed for
the linker to do it's main job, and is therefore not necessarily
available to it. That's part of the reason why the C standard does not
require generation of any diagnostic message for this kind of problem.

As for how it works - the definition of var in f1.c causes a piece of
memory to be set aside that is sufficiently large and correctly aligned
to store an object of type 'float'. That piece of memory is extremely
unlikely to be large enough to store an object of type 'double', and
might not be correctly aligned to store one.

The declaration of var as a double with external linkage in main.c
causes the linker to determine the address reserved for an identifier
with external linkage named 'var' and to insert that address into the
locations in the code implementing main() that need the address of 'var'
(I speak of the way linkers work on the systems I'm most familiar with -
there probably are other ways that can be used to achieve the same
effect). It doesn't need to know the type of thing stored at that
address in order to do this.

When executing the instructions implementing main() that are supposed to
refer to value of 'var', the program tries to retrieve the value of an
object of type 'double' that it assumes is stored that address. Since
there is no such object, this is where things are likely to go wrong.
The most likely situation is that it looked at sizeof(double) bytes of
memory, starting with the bytes storing the f1.c 'var', but also
including additional bytes of memory that may have been allocated for
some other purpose entirely. Those bytes might not even be ones that
your process has permission to access. If it does have such permissions,
it will interpret those bytes as if they contained a representation of a
'double' value; they need not contain a valid representation, and are
extremely unlikely to contain a valid representation of the same value
that was stored by f1.c in 'var'.

Does that answer your question?
--
James Kuyper
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Difference of extern short *x and extern short x[]? Andre C Programming 5 07-17-2012 07:38 PM
Use of 'extern' keyword siliconwafer C Programming 5 07-31-2005 03:39 AM
how to use the keyword extern in c? ooze C Programming 16 08-30-2004 04:39 PM
extern const char * vs. extern const char []http://tinyurl.com/47e3k Thomas Matthews C++ 5 08-02-2004 10:36 AM
keyword extern tweak C Programming 18 06-29-2004 11:20 AM



Advertisments