473,396 Members | 1,676 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

"extern" question?

I have 3 files (see below: a.h, w.c, ww.c). I would like to use a
single x (declared somewhere) which would global to both compilation
units: w.c & ww.c. No matter where I place the "extern" qualifier - it
appears to work: x is shared between w.c and ww.c. Or if I simple
don't use "extern", it works. Why? What is the correct (or simply
preferred) usage?

---John

PSI'm using gcc (GCC) 4.0.2.

/*---------------a.h-----------------*/
#ifndef _A_H
#define _A_H

extern int x;
void g( void );

#endif /* _A_H */

/*---------------w.c-----------------*/
#include <stdio.h>
#include <stdlib.h>
#include "a.h"

int x;

void g( void )
{
x = 12;
fprintf( stderr, "x = %d\n", x );
}

/*---------------ww.c-----------------*/
#include <stdio.h>
#include <stdlib.h>
#include "a.h"

int x;

int main( int argc, char *argv[] )
{
g();
x = 144;
fprintf( stderr, "x = %d\n", x );
g();
fprintf( stderr, "x = %d\n", x );
}

Aug 15 '06 #1
5 1908
On 15 Aug 2006 12:27:14 -0700, "jc**********@gmail.com"
<jc**********@gmail.comwrote in comp.lang.c:
I have 3 files (see below: a.h, w.c, ww.c). I would like to use a
single x (declared somewhere) which would global to both compilation
units: w.c & ww.c. No matter where I place the "extern" qualifier - it
appears to work: x is shared between w.c and ww.c. Or if I simple
don't use "extern", it works. Why? What is the correct (or simply
preferred) usage?
The only CORRECT usage is to have one and only definition of the
object (a declaration without the extern keyword, or a declaration
with an initializer with or without the extern keyword) in one
translation unit, and a declaration with the extern keyword and no
initializer in every other translation unit that references the
object.

The preferred usage, is to put the external declaration (with extern,
without initializer) in a header and include that header in all
translation units that reference the object, including the one that
defines it.
PSI'm using gcc (GCC) 4.0.2.

/*---------------a.h-----------------*/
#ifndef _A_H
Here is something else that is not CORRECT. You violate the language
standard when you define identifiers beginning with two underscores,
or an underscore followed by an upper case letter, in your code. All
such identifiers with this pattern are reserved for the implementation
(compiler). Change this.
#define _A_H

extern int x;
void g( void );

#endif /* _A_H */

/*---------------w.c-----------------*/
#include <stdio.h>
#include <stdlib.h>
#include "a.h"

int x;

void g( void )
{
x = 12;
fprintf( stderr, "x = %d\n", x );
}

/*---------------ww.c-----------------*/
#include <stdio.h>
#include <stdlib.h>
#include "a.h"

int x;

int main( int argc, char *argv[] )
{
g();
x = 144;
fprintf( stderr, "x = %d\n", x );
g();
fprintf( stderr, "x = %d\n", x );
}
The C standard is quite specific about external definitions for
objects or functions. For an object or function that appears in an
external declaration but is not referenced by the program, there may
be either zero or one external definition. For an object or function
in an external declaration that is referenced by the program, there
must be exactly one and only one external definition. If a program
violates these conditions, the result is undefined behavior.

In your snippets, you show three different files that each have an
external definition of the int object x. That invokes undefined
behavior, since you have more than one definition. Once you produce
undefined behavior, the C standard no longer knows or cares what
happens, One possible result of undefined behavior is the program
might do what you expected it to do.

--
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.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Aug 15 '06 #2
Ark
Jack Klein wrote:
<snip>
The only CORRECT usage is to have one and only definition of the
object
<snip>
....with the notable exception of tentative definitions.
- Ark
Aug 16 '06 #3
On Tue, 15 Aug 2006 21:48:50 -0400, Ark <ak*****@macroexpressions.com>
wrote in comp.lang.c:
Jack Klein wrote:
<snip>
The only CORRECT usage is to have one and only definition of the
object
<snip>
...with the notable exception of tentative definitions.
- Ark
No, because a tentative definition is not an actual external
definition. 6.9.2 makes this quite clear. An external definition has
an initializer, while a tentative definition does not.

The wording of the standard makes this quite clear:

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

So the tentative definition itself is never an actual definition of an
object, but it causes the compiler to act "as if" there were an
external definition, that is one with an initializer of 0.

--
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.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Aug 16 '06 #4

jc**********@gmail.com wrote:
I have 3 files (see below: a.h, w.c, ww.c). I would like to use a
single x (declared somewhere) which would global to both compilation
units: w.c & ww.c. No matter where I place the "extern" qualifier - it
appears to work: x is shared between w.c and ww.c. Or if I simple
don't use "extern", it works. Why? What is the correct (or simply
preferred) usage?

---John

PSI'm using gcc (GCC) 4.0.2.

/*---------------a.h-----------------*/
#ifndef _A_H
#define _A_H

extern int x;
void g( void );

#endif /* _A_H */

/*---------------w.c-----------------*/
#include <stdio.h>
#include <stdlib.h>
#include "a.h"

int x;

void g( void )
{
x = 12;
fprintf( stderr, "x = %d\n", x );
}

/*---------------ww.c-----------------*/
#include <stdio.h>
#include <stdlib.h>
#include "a.h"

int x;

int main( int argc, char *argv[] )
{
g();
x = 144;
fprintf( stderr, "x = %d\n", x );
g();
fprintf( stderr, "x = %d\n", x );
}
Hi,

1. First of all extern is not a qualifier , it is a storage class
specifier. Because in C, type qualifier implies const and volatile.

2. Explicit "extern" declaration is needed only if the object
definition is in another source file, which the compiler cannot resolve
at compile time. They will be resolved only while linking the
module/Translation Unit(TU) containing the definition with the file
containing declaration.

3. If the definition is in the same source file as the
declaration,then, the "extern" keyword for declaration is optional.
Since the header is already included, that means the defintion is
present in this TU. Hence no explicit extern is needed.

Regards,
Sarathy

Aug 16 '06 #5
Ark
Jack Klein wrote:
On Tue, 15 Aug 2006 21:48:50 -0400, Ark <ak*****@macroexpressions.com>
wrote in comp.lang.c:
>Jack Klein wrote:
<snip>
>>The only CORRECT usage is to have one and only definition of the
object
<snip>
...with the notable exception of tentative definitions.
- Ark

No, because a tentative definition is not an actual external
definition. 6.9.2 makes this quite clear. An external definition has
an initializer, while a tentative definition does not.

The wording of the standard makes this quite clear:

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

So the tentative definition itself is never an actual definition of an
object, but it causes the compiler to act "as if" there were an
external definition, that is one with an initializer of 0.
What I meant was:

1.
int x; //tentative or not?
The compiler doesn't know until the end of the translation unit.

2.
//four definitions, three of them tentative
int x;
int x;
int x;
int x /*maybe, = 2006, so "as-if" initializer ain't necessarily 0 */;

[I don't think we disagree on anything: I was just picking on "one and
only one". And tentative definitions are very real in that they legalize
(define?) addresses which can be used in looped static initializers like
void *head;
void *tail = &head;
void *head = &tail;
AFAIK, that's what they are for; but maybe there are uses that I don't
know about.
]
Aug 16 '06 #6

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

Similar topics

1
by: terrencel | last post by:
I was told to look at some old C code that was ported to C++. One of the file is like: ========================================= CPPClass* someCPPVar = NULL; extern "C" {
22
by: Ian | last post by:
The title says it all. I can see the case where a function is to be called directly from C, the name mangling will stuff this up. But I can't see a reason why a template function can't be...
10
by: Mark A. Gibbs | last post by:
I have a question about mixing C and C++. In a C++ translation unit, I want to define a function with internal linkage and C calling convention. Here's a sample of what I want to do: //...
12
by: G Patel | last post by:
I've seen some code with extern modifiers in front of variables declared inside blocks. Are these purely definitions (no definition) or are they definitions with static duration but external...
19
by: ccwork | last post by:
Hi all, I am reading "C: A Reference Manual" 4th ed and I get lost for the "extern". It says that global object without specifying the storage-class specifier will have "extern" as the default...
4
by: kk_oop | last post by:
Hi. I need to write a C++ callback function and register it with a C program. I've read that this can be done if the callback function is a static method. I've also read that I should use a...
4
by: mimi | last post by:
The programmer indicates to the compiler that a function is written in a different programming language using a linkage directives.It is intuitive that extern "SomeLanguage" is used to declare...
17
by: William Pursell | last post by:
I debated whether this belongs in comp.lang.c++, and finally decided that it belongs here, because it really is a C question... Suppose I have a perfectly friendly, harmless library, libfoo,...
8
by: bob | last post by:
Hi, we're faced with a horrible scenario whereby we are not able to access exported classes in a DLL due to cross compiler issues. Traditional approaches such as using extern "C" and...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
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...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
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...

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.