Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

mixing `extern' and `static' declarations

14 views
Skip to first unread message

Fergus Henderson

unread,
Sep 3, 1998, 3:00:00 AM9/3/98
to
Could someone please tell me if my interpretation of the C standard
for the following code is correct?

/* example 1 */
extern const struct foo_struct foo;
...
static const struct foo_struct { ... } foo = { ... };

I believe this example has undefined behaviour according to 6.1.2.2,
since the first occurrence of `foo' has external linkage (paragraph 4,
"if no prior declaration is visible ... then the identifier has
external linkage"), and the second occurrence has internal linkage
(paragraph 3), and so the behaviour is undefined (paragraph 7).

However, if the order of the declarations is swapped, i.e.

/* example 2 */
static const struct foo_struct { ... } foo = { ... };
...
extern const struct foo_struct foo;

then I believe it is OK, because paragraph 4 of 6.1.2.2 says that
second declaration gets the linkage of the prior declaration,
i.e. internal linkage, so they both specify internal linkage.

Is this all correct?

--
Fergus Henderson <f...@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger f...@128.250.37.3 | -- the last words of T. S. Garp.

Norman Diamond

unread,
Sep 4, 1998, 3:00:00 AM9/4/98
to
In article <6slfg7$f20$1...@mulga.cs.mu.OZ.AU>, f...@cs.mu.oz.au (Fergus Henderson) writes:
> extern const struct foo_struct foo;
> static const struct foo_struct { ... } foo = { ... };
>I believe this example has undefined behaviour according to 6.1.2.2,
>since the first occurrence of `foo' has external linkage (paragraph 4,
>"if no prior declaration is visible ... then the identifier has
>external linkage"), and the second occurrence has internal linkage
>(paragraph 3), and so the behaviour is undefined (paragraph 7).

>However, if the order of the declarations is swapped, i.e.
> static const struct foo_struct { ... } foo = { ... };

> extern const struct foo_struct foo;
>then I believe it is OK, because paragraph 4 of 6.1.2.2 says that
>second declaration gets the linkage of the prior declaration,
>i.e. internal linkage, so they both specify internal linkage.

Yup. I thought this was understood 10 years ago. After the success of
this experiment, they went on to bigger and better semantic algorithms.
You should see the contortions that were added with "inline".

By the way, here's another example for you:


static const struct foo_struct { ... } foo = { ... };

const struct foo_struct foo;
Undefined again. I'm looking at C9x CD1 but believe it was the same in
C89. Look at paragraph 5 sentence 2 (and if necessary, look at sentence
1 and notice how sentence 2 differs), then paragraph 7.

--
<< If this were the company's opinion, I would not be allowed to post it. >>
"I paid money for this car, I pay taxes for vehicle registration and a driver's
license, so I can drive in any lane I want, and no innocent victim gets to call
the cops just 'cause the lane's not goin' the same direction as me" - J Spammer

Fergus Henderson

unread,
Sep 4, 1998, 3:00:00 AM9/4/98
to
dia...@tbj.dec.com (Norman Diamond) writes:

>f...@cs.mu.oz.au (Fergus Henderson) writes:
>> extern const struct foo_struct foo;
>> static const struct foo_struct { ... } foo = { ... };
>>I believe this example has undefined behaviour according to 6.1.2.2,
>>since the first occurrence of `foo' has external linkage (paragraph 4,
>>"if no prior declaration is visible ... then the identifier has
>>external linkage"), and the second occurrence has internal linkage
>>(paragraph 3), and so the behaviour is undefined (paragraph 7).

...


>Yup. I thought this was understood 10 years ago.

OK, next question. Suppose I try to repair this example by making
the forward declaration specify `static' rather than `extern':

static const struct foo_struct foo;
...


static const struct foo_struct { ... } foo = { ... };

Now, if I interpret the standard correctly, this is still undefined
behaviour, since it violates a "Semantics" section of 6.7.2: paragraph
3 says that the forward declaration is actually a tentative definition,
and paragraph 4 says "If the declaration of an identifier for an object
is a tentative definition and has internal linkage, the declared type
shall not be an incomplete type". Drats!

What's the rationale for this rule?

(I checked the Rationale, but it didn't say much about this one.)

Am I correct in inferring that there is no standard-conforming way of giving
a forward declaration for an object with internal linkage and incomplete type?

Norman Diamond

unread,
Sep 7, 1998, 3:00:00 AM9/7/98
to
In article <6sodjq$ptp$1...@mulga.cs.mu.OZ.AU>, f...@cs.mu.oz.au (Fergus Henderson) writes:
> static const struct foo_struct foo;
> static const struct foo_struct { ... } foo = { ... };
>violates a "Semantics" section of 6.7.2: paragraph 3 says that the forward
>declaration is actually a tentative definition, and paragraph 4 says "If
>the declaration of an identifier for an object is a tentative definition
>and has internal linkage, the declared type shall not be an incomplete type".
>What's the rationale for this rule?

Everyone assumed that linkers would be smarter than compilers?
(Since this could be done with an extern.)

Everyone assumed that if you wanted two constant structures to contain
pointers to each other, you'd assign the pointers by using a cast to
a non-const type and put the assignments in your "atentry" function?

Hmm, let's see. If there's no actual definition then a definition is
created based on tentative definitions. Maybe the committee forgot
that there's a way to form a composite tentative definition from a set
of tentative definitions? Or maybe the committee was worried that even
a composite tentative definition might still be incomplete? But even in
this case, an initializer consisting of { 0 } would set an array length
to 1. A structure would have to be completed by the translation unit
somewhere along the line.

0 new messages