473,387 Members | 1,745 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,387 software developers and data experts.

Doubts about Linkage Rules

source: http://rm-f.net/~orange/devel/specif...t.html#3.1.2.2

there are two passages in this paragraph i can't fully understand:

1) "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. If there is no visible declaration with file scope, the
identifier has external linkage."

in particular: "the identifier has the same linkage as /any/ /visible/
declaration of the identifier with file scope"

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

i can't imagine an example of an identifier having both internal and
external linkage...
Apr 17 '06 #1
13 2050
fctk wrote:
source: http://rm-f.net/~orange/devel/specif...t.html#3.1.2.2

there are two passages in this paragraph i can't fully understand:

1) "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. If there is no visible declaration with file scope, the
identifier has external linkage."

in particular: "the identifier has the same linkage as /any/ /visible/
declaration of the identifier with file scope"
It means that the following is a legal declaration of foo with file
linkage scope:

static int foo;
extern int foo;

and this a legal declaration of bar with external linkage scope:

int bar;
extern int bar;

The rationale document for C89 explains how this requirement allows the
implementation of a one-pass compiler that generates intermediate
assembly code.

Note that C99 clarifies the *visible* part of the specification as
follows (6.2.2):

"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 specifies no linkage, then the
identifier has external linkage."
2) "If, within a translation unit, the same identifier appears with both
internal and external linkage, the behavior is undefined."

i can't imagine an example of an identifier having both internal and
external linkage...


This is not allowed:

static int bar;
int bar;

--
Diomidis Spinellis
Code Quality: The Open Source Perspective (Addison-Wesley 2006)
http://www.spinellis.gr/codequality
Apr 17 '06 #2
fctk <-> wrote:

there are two passages in this paragraph i can't fully understand: [...] in particular: "the identifier has the same linkage as /any/ /visible/
declaration of the identifier with file scope"
Visibility of identifiers is discussed in 6.2.1p2. Consider:

extern int i;
static int i;

The second declaration is not yet visible at the first declaration, so
the first declaration declares i to have external linkage.
i can't imagine an example of an identifier having both internal and
external linkage...


See above. :-)

If the declarations were reversed, all would be well since the "static"
declaration would be visible at the "extern" declaration and thus the
"extern" declaration would declare "i" with internal linkage, too.

-Larry Jones

How am I supposed to learn surgery if I can't dissect anything? -- Calvin
Apr 17 '06 #3
Diomidis Spinellis ha scritto:
fctk wrote:
2) "If, within a translation unit, the same identifier appears with
both internal and external linkage, the behavior is undefined."

i can't imagine an example of an identifier having both internal and
external linkage...

This is not allowed:

static int bar;
int bar;


i can't understand why there is a problem with:

static int bar;
int bar;

let me expand the previous example to something as:

static int bar; /* first declaration of `bar' */

void f1(void) {
bar;
}

int bar; /* second declaration of `bar' */

void f2(void) {
bar;
}

first of all let's highlight the scopes of the two declarations of
`bar'; i will put an /* 1 */ in front of all lines that belongs to the
scope of the first declaration, and an /* 2 */ in front of all lines
that belong to the scope of the second declaration:

static int bar; /* first declaration of `bar' */
/* 1 */
/* 1 */ void f1(void) {
/* 1 */ bar;
/* 1 */ }
/* 1 */
int bar; /* second declaration of `bar' */
/* 2 */
/* 2 */ void f2(void) {
/* 2 */ bar;
/* 2 */ }

both declarations of `bar' have file-scope, becouse they are put outside
of any block and outside of any list of parameter declarations in a
function definition.

please note that, as far as i know, given a certain identifier `foo',
the scope of a declaration of `foo' and the scope of another declaration
of `foo' *can't* overlap. overlapping is possible only for the scopes of
*different* identifiers declarations.

the relevant rules here for the linkage are:

1) If the declaration of an identifier for an object or a function has
file scope and contains the storage-class specifier static, the
identifier has internal linkage.

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

so for rule 1) all instances of identifier `bar' within the scope of the
first declaration of `bar' have internal-linkage, while for rule 2) all
instances of identifier `bar' within the scope of the second declaration
of `bar' have external-linkage:

static int bar; /* first declaration of `bar' */
/* 1 */
/* 1 */ void f1(void) {
/* 1 */ bar; /* this instance has internal-linkage */
/* 1 */ }
/* 1 */
int bar; /* second declaration of `bar' */
/* 2 */
/* 2 */ void f2(void) {
/* 2 */ bar; /* this instance has external-linkage */
/* 2 */ }

so as far as i know there is no instance of some identifier with *both*
internal-linkage and external-linkage.

of course my reasoning is wrong in some points, but i can't understand
where.

sorry for the long message.
Apr 18 '06 #4

fctk wrote:
Diomidis Spinellis ha scritto:
fctk wrote:
2) "If, within a translation unit, the same identifier appears with
both internal and external linkage, the behavior is undefined."

i can't imagine an example of an identifier having both internal and
external linkage...

This is not allowed:

static int bar;
int bar;


i can't understand why there is a problem with:


<snip>
first of all let's highlight the scopes of the two declarations of
`bar'; i will put an /* 1 */ in front of all lines that belongs to the
scope of the first declaration, and an /* 2 */ in front of all lines
that belong to the scope of the second declaration:

static int bar; /* first declaration of `bar' */
/* 1 */
/* 1 */ void f1(void) {
/* 1 */ bar;
/* 1 */ }
/* 1 */
int bar; /* second declaration of `bar' */
/* 2 */
/* 2 */ void f2(void) {
/* 2 */ bar;
/* 2 */ }


<snip>

I think your problem is in not understanding scopes properly. The above
example should read (using your notation):

static int bar; /* first declaration of `bar' */
/* 1 */
/* 1 */ void f1(void) {
/* 1 */ bar;
/* 1 */ }
/* 1 */
/* 1 */ int bar; /* second declaration of `bar' */ /* BANG! */
/* 1 */
/* 1 */ void f2(void) {
/* 1 */ bar;
/* 1 */ }

As file scope spans the whole of the file (hence the name).

Functions `f1()` and `f2()` have inner scopes of their own, where you
can declare `bar` again, but that `bar` then is local to the function,
and masks the file scope one from the line where it's declared till the
closing brace of the function.

Apr 18 '06 #5
Vladimir S. Oka ha scritto:
I think your problem is in not understanding scopes properly. The above
example should read (using your notation):

static int bar; /* first declaration of `bar' */
/* 1 */
/* 1 */ void f1(void) {
/* 1 */ bar;
/* 1 */ }
/* 1 */
/* 1 */ int bar; /* second declaration of `bar' */ /* BANG! */
/* 1 */
/* 1 */ void f2(void) {
/* 1 */ bar;
/* 1 */ }

As file scope spans the whole of the file (hence the name).


did you mean perhaps something as:

static int bar; /* first declaration of `bar' */
/* 1 */
/* 1 */ void f1(void) {
/* 1 */ bar;
/* 1 */ }
/* 1 */
/* 1 */ int bar; /* second declaration of `bar' */
/* 1 */ /* 2 */
/* 1 */ /* 2 */ void f2(void) {
/* 1 */ /* 2 */ bar;
/* 1 */ /* 2 */ }

?

with the previous notation i mean: the scope of the first declaration
overlaps with the scope of the second declaration from line 8 to line
11, and the second declaration "masks" the first declaration from line 8
to line 11.
Apr 18 '06 #6

fctk wrote:
Vladimir S. Oka ha scritto:
I think your problem is in not understanding scopes properly. The above
example should read (using your notation):

static int bar; /* first declaration of `bar' */
/* 1 */
/* 1 */ void f1(void) {
/* 1 */ bar;
/* 1 */ }
/* 1 */
/* 1 */ int bar; /* second declaration of `bar' */ /* BANG! */
/* 1 */
/* 1 */ void f2(void) {
/* 1 */ bar;
/* 1 */ }

As file scope spans the whole of the file (hence the name).


did you mean perhaps something as:

static int bar; /* first declaration of `bar' */
/* 1 */
/* 1 */ void f1(void) {
/* 1 */ bar;
/* 1 */ }
/* 1 */
/* 1 */ int bar; /* second declaration of `bar' */
/* 1 */ /* 2 */
/* 1 */ /* 2 */ void f2(void) {
/* 1 */ /* 2 */ bar;
/* 1 */ /* 2 */ }

?

with the previous notation i mean: the scope of the first declaration
overlaps with the scope of the second declaration from line 8 to line
11, and the second declaration "masks" the first declaration from line 8
to line 11.


Yes, but you can't have the above. The second declaration is illegal.
That's why I did not include /* 2 */ in my example (I've added a /*
BANG! */, though).

Apr 18 '06 #7
Vladimir S. Oka ha scritto:
fctk wrote:

did you mean perhaps something as:

static int bar; /* first declaration of `bar' */
/* 1 */
/* 1 */ void f1(void) {
/* 1 */ bar;
/* 1 */ }
/* 1 */
/* 1 */ int bar; /* second declaration of `bar' */
/* 1 */ /* 2 */
/* 1 */ /* 2 */ void f2(void) {
/* 1 */ /* 2 */ bar;
/* 1 */ /* 2 */ }

?

with the previous notation i mean: the scope of the first declaration
overlaps with the scope of the second declaration from line 8 to line
11, and the second declaration "masks" the first declaration from line 8
to line 11.

Yes, but you can't have the above. The second declaration is illegal.
That's why I did not include /* 2 */ in my example (I've added a /*
BANG! */, though).


ok, now i think i understand why the second instance of `bar' in my
example has both internal and external linkage.

anyway i don't understand why the following piece of code (without f1
and f2 functions) is wrong:

static int bar;
int bar;

the previous gets re-written as:

static int bar; /* first declaration of identifier `bar' */
/* 1 */
/* 1 */ int bar; /* second declaration of identifier `bar' */
/* 1 */ /* 2 */

there is *no* instance of identifier `bar' in the scope of some
declaration. so it is false that there is an instance of `bar' with both
external and internal linkage.

when trying to compile, i get:

error: non-static declaration of 'bar' follows static declaration
error: previous declaration of 'bar' was here

i'm sure there is something else i haven't fully understood yet.
Apr 18 '06 #8

fctk wrote:
Vladimir S. Oka ha scritto:
fctk wrote:

did you mean perhaps something as:

static int bar; /* first declaration of `bar' */
/* 1 */
/* 1 */ void f1(void) {
/* 1 */ bar;
/* 1 */ }
/* 1 */
/* 1 */ int bar; /* second declaration of `bar' */
/* 1 */ /* 2 */
/* 1 */ /* 2 */ void f2(void) {
/* 1 */ /* 2 */ bar;
/* 1 */ /* 2 */ }

?

with the previous notation i mean: the scope of the first declaration
overlaps with the scope of the second declaration from line 8 to line
11, and the second declaration "masks" the first declaration from line 8
to line 11.

Yes, but you can't have the above. The second declaration is illegal.
That's why I did not include /* 2 */ in my example (I've added a /*
BANG! */, though).


ok, now i think i understand why the second instance of `bar' in my
example has both internal and external linkage.

anyway i don't understand why the following piece of code (without f1
and f2 functions) is wrong:

static int bar;
int bar;

the previous gets re-written as:

static int bar; /* first declaration of identifier `bar' */
/* 1 */
/* 1 */ int bar; /* second declaration of identifier `bar' */
/* 1 */ /* 2 */

there is *no* instance of identifier `bar' in the scope of some
declaration. so it is false that there is an instance of `bar' with both
external and internal linkage.

when trying to compile, i get:

error: non-static declaration of 'bar' follows static declaration
error: previous declaration of 'bar' was here

i'm sure there is something else i haven't fully understood yet.


Maybe you should try thinking about this particular example in this
way:

static int bar;

Tells the compiler that `bar` is "visible" only internally to the file
in question.

int bar;

Then tells the compiler that it is "visible" externally as well.

Logically, both can't be true at the same time, hence the error.

Apr 18 '06 #9
Vladimir S. Oka ha scritto:
Maybe you should try thinking about this particular example in this
way:

static int bar;

Tells the compiler that `bar` is "visible" only internally to the file
in question.

int bar;

Then tells the compiler that it is "visible" externally as well.

Logically, both can't be true at the same time, hence the error.


mmh... but i think there is another error. `static int bar' and `int
bar' are two *definitions* other than two declarations. they are two
definitions of the *same* object.

it is as if i wrote:

static void f1(void) {}
extern void f1(void) {}

isn't it?
Apr 18 '06 #10

fctk wrote:
Vladimir S. Oka ha scritto:
Maybe you should try thinking about this particular example in this
way:

static int bar;

Tells the compiler that `bar` is "visible" only internally to the file
in question.

int bar;

Then tells the compiler that it is "visible" externally as well.

Logically, both can't be true at the same time, hence the error.


mmh... but i think there is another error. `static int bar' and `int
bar' are two *definitions* other than two declarations. they are two
definitions of the *same* object.

it is as if i wrote:

static void f1(void) {}
extern void f1(void) {}

isn't it?


Yes, that too. I was just pointing out the other discrepancy.

Apr 18 '06 #11
Diomidis Spinellis ha scritto:
It means that the following is a legal declaration of foo with file
linkage scope:

static int foo;
extern int foo;

[...]

Note that C99 clarifies the *visible* part of the specification as
follows (6.2.2):

"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 specifies no linkage, then the
identifier has external linkage."


sorry but i don't understand.

let me rewrite that example as follows:

static int foo; /* D1 */
/* S1 */
/* S1 */ extern int foo; /* D2 */
/* S1 */ /* S2 */

/* D1 */ : declaration1; first declaration of identifier `foo'
/* D2 */ : declaration2; second declaration of identifier `foo'
/* S1 */ : scope1; scope of the first declaration
/* S2 */ : scope2; scope of the second declaration

i don't understand this passage of the rule: "for an identifier declared
[...] in a scope in which a *prior* declaration of that identifier /is/
/visible/, [...]".

D2 is inside S1. let suppose S1 is "visible" to D2. the problem is D1 is
*not* inside S1, so D2 does not know the existence of D1.

this problem could be resolved by "extending" the scopes in the
following way:

/* S1 */static int foo; /* D1 */
/* S1 */
/* S1 */ /* S2 */ extern int foo; /* D2 */
/* S1 */ /* S2 */

all `foo's would have interal-linkage. (( question: but do the instance
of an identifier which occour in a declaration of that identifier have a
kind of linkage? ))

anyway, this "extension" would contract with this other rule:

"Structure, union, and enumeration tags have scope that begins [...].
Each enumeration constant has scope that begins [...]. Any other
identifier has scope that begins /just/ /after/ the completion of its
declarator."
Apr 18 '06 #12
Vladimir S. Oka wrote:
fctk wrote:
Vladimir S. Oka ha scritto:
Maybe you should try thinking about this particular example in this
way:

static int bar;

Tells the compiler that `bar` is "visible" only internally to the file
in question.

int bar;

Then tells the compiler that it is "visible" externally as well.

Logically, both can't be true at the same time, hence the error.

mmh... but i think there is another error. `static int bar' and `int
bar' are two *definitions* other than two declarations. they are two
definitions of the *same* object.

it is as if i wrote:

static void f1(void) {}
extern void f1(void) {}

isn't it?


Yes, that too. I was just pointing out the other discrepancy.


Actually no, they are both tentative definitions, where as you example
with functions shows definitions. For example, the following is
completely legal:

static int bar; /* tentative definition */
static int bar; /* tentative definition */
static int bar; /* tentative definition */
static int bar; /* tentative definition */
static int bar = 5; /* definition */

This defines only one object named bar which is of type int and is
initialised to 5.

From section 6.9.2 of n1124.pdf
| 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.

Here is example 1 from the same section:
int i1 = 1; // definition, external linkage
static int i2 = 2; // definition, internal linkage
extern int i3 = 3; // definition, external linkage
int i4; // tentative definition, external linkage
static int i5; // tentative definition, internal linkage
int i1; // valid tentative definition, refers to pre vious
int i2; // 6.2.2 renders undefined, linkage disagreement
int i3; // valid tentative definition, refers to pre vious
int i4; // valid tentative definition, refers to pre vious
int i5; // 6.2.2 renders undefined, linkage disagreement
extern int i1; // refers to pre vious, whose linkage is external
extern int i2; // refers to pre vious, whose linkage is internal
extern int i3; // refers to pre vious, whose linkage is external
extern int i4; // refers to pre vious, whose linkage is external
extern int i5; // refers to pre vious, whose linkage is internal

Note that there are only two problem lines in the above example, delete
(or correct) those two lines and it would be completely legal C99 (if
not for the // style comments it would be legal C89 as well).
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc
Apr 18 '06 #13

Flash Gordon wrote:
Vladimir S. Oka wrote:
fctk wrote:
Vladimir S. Oka ha scritto:
Maybe you should try thinking about this particular example in this
way:

static int bar;

Tells the compiler that `bar` is "visible" only internally to the file
in question.

int bar;

Then tells the compiler that it is "visible" externally as well.

Logically, both can't be true at the same time, hence the error.

mmh... but i think there is another error. `static int bar' and `int
bar' are two *definitions* other than two declarations. they are two
definitions of the *same* object.

it is as if i wrote:

static void f1(void) {}
extern void f1(void) {}

isn't it?


Yes, that too. I was just pointing out the other discrepancy.


Actually no, they are both tentative definitions, where as you example
with functions shows definitions.


Right. I stand corrected on the variable part. Should've been more
careful.

After all, speed /is/ the device of shaitan.

Apr 18 '06 #14

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

Similar topics

5
by: Web Developer | last post by:
Hi, I read that identifiers should not start with an underscore in order to prevent LINKAGE problems. I am not familar with this concept of "linkage", so can someone provide a simple...
9
by: qazmlp | last post by:
const has internal linkage in C++, but external linkage in C. Am I right ? But, linker reports multiply-defined error if the following header is included in multiple .cpp files. //...
47
by: Richard Hayden | last post by:
Hi, I have the following code: /******************************** file1.c #include <iostream> extern void dummy(); inline int testfunc() {
20
by: Grumble | last post by:
Hello everyone, As far as I understand, the 'inline' keyword is a hint for the compiler to consider the function in question as a candidate for inlining, yes? What happens when a function with...
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: //...
4
by: project | last post by:
Anybody can solve following doubts? 1. Normalization rules. 2. Garbage Collection 3.LinkList Posted Via Usenet.com Premium Usenet Newsgroup Services...
3
by: al.cpwn | last post by:
do static and inline functions or members have internal linkage? I have been reading this newsgroup on google and found conflicting ideas. Can someone please help me understand why in some places...
3
by: Rahul Babbar | last post by:
Hi, I had the following doubts about the "For Read Only" clause. 1. How does a "for Read only" clause improve the performance? 2. How does a "for Read only" clause compare with "With UR"...
1
by: Giacomo Catenazzi | last post by:
Hello, To learn the details of C, I've build the following example, could you check if it is correct and if it miss some important cases? Are there some useful (real cases) examples of: -...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
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
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
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.