Re: extern



Mark McIntyre wrote:
> On Wed, 20 Jul 2005 13:39:13 +0100, in comp.lang.c , Lawrence Kirby
> <lknews@xxxxxxxxxxxxxxx> wrote:
>
> >On Wed, 20 Jul 2005 12:03:08 +0100, Mark McIntyre wrote:
> >
> >> On Tue, 19 Jul 2005 21:43:12 -0500, in comp.lang.c , Jack Klein
> >> <jackklein@xxxxxxxxxxx> wrote:
> >>
> (of two files with int a; in them)
>
> >>>If you compile these two source files and combine them into a single
> >>>executable, you produce undefined behavior.
> >>
> >> You sure? The second behaves exactly as if it had been declared
> >> extern int a;

The same was my understanding until this thread, so perhaps I can
explain it knowing where you're coming from, because actually it
behaves as if it had been declared extern int a = 0;

> >Both have identical (external) linkage but their behaviour in terms of
> >whether they create a definition is different.
> >
> >As such both a.c and b.c contain a definition of a so linking them
> >produces undefined behaviour.
>
> Really? The standard makes it pretty clear that in the absence of a
> storage class specifier, a file-scope object is considered to be
> extern.

You are probably referring to 6.2.2#5. As Chris Torek points out, this
section specifies that the extern keyword gives the object external
linkage. Aside from linkage, there are two other relevant contexts in
which the word "external" can be applied: to a declaration and to a
definition.

> And FWIW I can't recall a compiler that behaves otherwise than
> to consider two such declarations to be synonyms. I confess, my
> initial thought was the same as yours, but closer reading of the
> standard deconvinced me. Can you point me to the actual section that
> confirms your view?

You seem to already know the part of the standard requiring that int a;
is treated as extern int a;

6.2.2#5
....
If the declaration of an identifier for
an object has file scope and no storage-class specifier, its
linkage is external.

Below an external declaration is defined as a file-scope declaration,
where it is also clarified that an initialiser turns a declaration into
a definition:

6.9#4
As discussed in 5.1.1.1, the unit of program text after
preprocessing is a translation unit, which consists of a
sequence of external declarations. These are described as
``external'' because they appear outside any function (and
hence have file scope). As discussed in 6.7, a declaration
that also causes storage to be reserved for an object or a
function named by the identifier is a definition.

Below we find out that int a; becomes int a = 0; by end of file in the
absence of other definitions. i.e. 6.2.2#5, 6.9#4 and 6.9.2#2 require
that our external declaration int a; by file end becomes the external
definition with external linkage: extern int a = 0.

6.9.2#2
[#2] 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.

Below we find that a program shall only have one external definition
for each identifier that is actually used. Given that our two files
each contain an identical variable declaration that ultimately becomes
an external definition, this constraint is violated (unless the
variable is not actually used).

6.9#5
An external definition is an external declaration that
is also a definition of a function or an object. If an
identifier declared with external linkage is used in an
expression (other than as part of the operand of a sizeof
operator), somewhere in the entire program there shall be
exactly one external definition for the identifier;
otherwise, there shall be no more than one.127)
____________________

127Thus, if an identifier declared with external linkage is
not used in an expression, there need be no external
definition for it.

Quite a chain of reasoning for the simple conclusion: we must use
extern for one of the declarations.

.



Relevant Pages

  • Re: Clarification required for linkage.
    ... According to me int g;is the tentative definition of g and it has ... linkage as if the "extern" keyword had been present. ... If the declaration of an identifier for a function has no storage- ...
    (comp.lang.c)
  • Re: redeclaration of p with no linkage
    ... Such objects have 'no linkage' and you can't have two of them in the ... "For an identifier declared with the storage-class specifier extern in ... the prior declaration specifies internal or external linkage, ... Identifiers declared within a block and without the extern keyword ...
    (comp.lang.c)
  • Re: frequently asked C and C++ interview questions along with their answers
    ... The extern behaviour I said is an inherited ... > If the declaration of an identifier for an object has file scope ... the declaration is an external definition for the ... If a translation unit contains one or more tentative ...
    (comp.lang.cpp)
  • Re: Doubts about Linkage Rules
    ... "If the declaration of an identifier for an object or a function contains the storage-class specifier extern, the identifier has the same linkage as any visible declaration of the identifier with file scope. ...
    (comp.lang.c)
  • Re: C Strings not returning from a function
    ... And as soon as mallocis declared as returning int, ... new declaration is used, the behaviour is undefined. ... identifier as a macro name, ...
    (comp.lang.c)