Re: Clarification required for linkage.



somenath wrote:
int g;
int g = 23;

The question is why compilation of the code is error free.
According to me int g;is the tentative definition of g and it has
linkage as if the "extern" keyword had been present. So it has
external linkage.

Correct. It's a tentative definition with external linkage. But there is a
subtle point. Note carefully the wording of 6.2.2{5}:

If the declaration of an identifier for a function has no storage-
class specifier, its linkage is determined exactly as if it were
declared with the storage-class specifier extern. If the declaration
of an identifier for an object has file scope and no storage-class
specifier, its linkage is external.

See how there's no "as if it were declared with ... extern" for object
declarations as there is for function declarations? To understand why,
suppose your code was missing the "int g = 23;" and had only the tentative
definition "int g;". If the object had an implied "extern", i.e., "extern
int g;", then you wouldn't end up with a definition by the end of
translation as you would with "int g;". The Standard would allow "extern
int g;", even though there's no corresponding definition in the program as
a whole.

Unfortunately, it gets even more subtle than that. Consider the following
*illegal* code:

static int g;
int g;

This is illegal because the first declaration has internal linkage,
whereas the second declaration has external linkage. And this violates
6.2.2{7}:

If, within a translation unit, the same identifier appears with
both internal and external linkage, the behavior is undefined.

However, *if* "int g;" carried an implied "extern" -- which it doesn't --
the code would be equivalent to the *legal*

static int g;
extern int g;

That's legal because of 6.2.2{4}:

For an identifier declared with the storage-class specifier extern
in a scope in which a prior declaration of that identifier is
visible, if the prior declaration specifies internal or external
linkage, the linkage of the identifier at the later declaration
is the same as the linkage specified at the prior declaration. If
no prior declaration is visible, or if the prior declaration
specifiers no linkage, then the identifier has external linkage.

So the second declaration, the one with the "extern", causes the second
'g' to have the internal linkage of the first 'g'.

Therefore, you shouldn't think of an implied "extern" for objects, because
the behavior with and without the "extern" can be very different.

In case of int g = 23; It is non tentative definition of g and the has
linkage as if the "extern" keyword had been present.
So it has external linkage.

Correct, but as above, don't think of an implied "extern" for objects.
Compare the illegal

static int g;
int g = 23;

with the presumably legal

static int g;
extern int g = 23;

The difficulty of interpretation can be seen in the fact that newer gcc
accepts the second code, whereas older gcc rejects it.

According to the C standard If, within a translation unit, the same
identifier appears with both internal and external linkage the
behavior is not defined.

Correct.

As g in both the case has external linkage that's the reason compiler
is not throwing error.

Correct.


Don't let it get you down. In my opinion, the overlapping concepts of
linkage, tentative definitions, external definitions, composite typing,
and related concepts are among the hardest C concepts to understand in
full -- a lot harder than pointers or the usual candidates for difficulty,
I think. This post is by no means complete (maybe not even entirely
correct, so await other replies), but I hope it has shed some light. Let
me know if you have any further problems.


Yours,
Han from China

--
"Only entropy comes easy." -- Anton Chekhov

.



Relevant Pages

  • Re: extern decleration intialization
    ... >"extern" is a reference to a variable with static storage class ... A static-duration object -- a variable, or the contents of a string, ... into scope until partway through the declaration. ... The "linkage" of an identifier has to do with whether the identifier ...
    (comp.lang.c)
  • Re: Specifier extern
    ... extern int b; // my line 6 ... more of an exercise for myself to see if I have a good grasp of linkage ... The outer one, at file scope, ... The "extern" keyword is particularly squirrely, ...
    (comp.lang.c)
  • Is the following undefined behavior?
    ... static int i; ... extern int i; ... declaration is visible with linkage, ...
    (comp.std.c)
  • Re: Can a static function declaration conflict with a non-static declaration?
    ... For an identifier declared with the storage-class specifier ... identifier is visible,23) if the prior declaration specifies ... internal or external linkage, ... "extern" keyword. ...
    (comp.lang.c)
  • Re: !!<====== Existence of a variable - Debunk a myth ======>!!
    ... If the declaration of an identifier for an object has ... tentative definition and has internal linkage, ... int i1; // valid tentative definition, ... extern int i1; // refers to previous, ...
    (comp.lang.c)