ridiculous warning or not?

K

Keith Thompson

Tim Rentsch said:
Now apply that to a tentative definition for an array,
but with the array having an incomplete type:

int some_array[]; // tentative

... no explicit definition, hence ...

int some_array[] = { 0 }; // this definition supplied implicitly

You see how the default sizing rule falls out of the rule
for default initialization of objects tentatively defined
but not explicitly defined? That rule wasn't written with
incomplete types in mind (I am guessing), but it has the
effect of completing them in the case of incomplete arrays.

I don't believe the normative wording actually says that, because of
a quibble about the phrase "equal to 0". I've posted to comp.std.c,
subject "Tentative array object definition".
 
B

Ben Bacarisse

Tim Rentsch said:
Ben Bacarisse said:
Tim Rentsch said:
[...snipped a lot, rearranged...]

A misunderstanding -- I use that style all the time.
Incidentally, a similar pattern is legal with struct's (or union's):

The same misunderstanding.

Okay, all good..
The thing I could see no sensible reason for writing was what
OP wrote: a tentative definition and nothing else. Explicitly
completing something later is very natural. Having it be
completed automatically is, to me, a little odd.

Probably I can imagine a scenario where havinng a default size
of one element would be useful. But it's easier to imagine
a scenario where having an option for a compiler warning is
more useful. :)

I don't quite see that. That the value should be zero, yes,
but why does it follow from them that there would be one
element in the array? Leaving the definition alone and thus
making the object incomplete seems to be just as natural a way
to treat the situation.

Ahh, because of the rule for how tentative definitions
are defined, without regard to incompleteness. Consider
this, a tentative definition for a complete struct type:

struct xyz { ... } some_struct; // tentative definition

... no explicit defintion, hence ...

struct xyz some_struct = { 0 }; // this definition supplied implicitly

Now apply that to a tentative definition for an array,
but with the array having an incomplete type:

int some_array[]; // tentative

... no explicit definition, hence ...

int some_array[] = { 0 }; // this definition supplied implicitly

You see how the default sizing rule falls out of the rule
for default initialization of objects tentatively defined
but not explicitly defined? That rule wasn't written with
incomplete types in mind (I am guessing), but it has the
effect of completing them in the case of incomplete arrays.

Right. I get that. What's bothering me is that I don't see these two
cases are comparable. In the first, it makes no odds if there is an
implicit "={0};" or not. In the second, it even alters the type! If
the rule were just that multiple tentative definitions are permitted and
that the final type is the composite type, the rules for default
initialisation of file-scope objects would do the rest. As far as I can
see, only arrays are altered by that final phrase "with an initializer
equal to zero".
 
K

Keith Thompson

Tim Rentsch said:
Keith Thompson said:
Tim Rentsch said:
So this:

char f[];

is treated as:

char f[] = 0;

No, it would be 'char f[] = {0};' as the implementation is
obliged to do by 6.7.9p16 -- implementations are obliged to
follow "shall" directives.

Implementations are obliged to follow *all* normative requirements
in the standard. 6.9.2p2 requires an implicit "initializer equal
to 0". I wouldn't say that `{0}` is "equal to 0".

[...snip-some-more...]
Apparently we have to interpret the "initializer equal to 0" to mean
`{ 0 }` rather than `0` in this case. And we're supposed to infer
from that that `f` has exactly one element; apparently `{ 0 }` is
"equal to 0" but `{ 0, 0 }` isn't.

{ 0, 0 } is two initializers, not one.

{ 0, 0 } is one initializer, which contains two more initializers.
[...snip elaboration...]

My comments were kind of half frivolous, because I find
it hard to believe someone would take this question so
seriously, when it seems perfectly obvious what is
intended. I do think my comments have some degree of
merit (and yours also), but not sufficient to overcome
the level of silliness present (for which I am more
to blame than you).

Therefore, rather than continuing on the particular
points above, I would like to quote from Defect Report #11
(slightly reformatted):
[snip]
Response
--------
Subclause 6.7.2 External object definitions contains the
following excerpt:

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.

This statement describes an effect and not a literal token
sequence. Therefore, this example does not contain an
error.

Please note the first sentence in the last paragraph.

Interesting. That's
http://www.open-std.org/JTC1/SC22/WG14/www/docs/dr_011.html
submitted 1992-12-10 against C90; it resulted in the addition of
the footnote in question.

Personally, I'm not satisfied with the statement that it "describes
an effect and not a literal token sequence", or with the conclusion
that an initializer "equal to 0" implies that the array has 1
element. The standard isn't a mathematically formal document, but
this is one of those cases where I think it needs to be more precise.
The phrase "equal to 0" has an exact meaning; I dislike the standard
using it so loosely.
 
T

Tim Rentsch

Ben Bacarisse said:
Right. I get that. What's bothering me is that I don't see
these two cases are comparable. In the first, it makes no odds
if there is an implicit "={0};" or not. In the second, it even
alters the type! If the rule were just that multiple tentative
definitions are permitted and that the final type is the
composite type, the rules for default initialisation of
file-scope objects would do the rest. As far as I can see,
only arrays are altered by that final phrase "with an
initializer equal to zero".

Ahh, now I see what you were saying.

If you'll allow me to speculate... way back when, as the
original standardization effort was under way in the late 1980's,
the rule for initializing tentative object definitions (in what
is now section 6.9.2) was done relatively early, with the wording
"with an initializer equal to 0", which appeared in C89/C90. The
fixup for non-scalar types was done later (ie after the decision
about object defintions but still part of C89). The wording from
the section on initialization (ie, in what is now 6.7.9 in C11)
that appeared in C89 is interesting:

If an object that has static storage duration is not
initialized explicitly, it is initialized implicitly as if
every member that has arithmetic type were assigned 0 and
every member that has pointer type were assigned a null
pointer constant.

It's like they wrote the two rules independently: one rule about
external object definitions that was written with scalar types in
mind, another rule in the section on initializers that was written
with non-scalar types in mind. Possibly the two sections were
written independently, or mostly independently, each side roughly
filling in the holes of the other. In any case, once the decision
about what to say for external object definitions was done, the
remaining passages were filled in focusing on non-scalar types,
and that ended up in the section on initialization.

Again, this is all speculation on my part. I did take clues from
the C89/C90 text, and also from the Rationale (C99V5.10), so
it wasn't a completely uninformed guess. More of a only very
mildly informed guess. :)
 
T

Tim Rentsch

Keith Thompson said:
Tim Rentsch said:
Now apply that to a tentative definition for an array,
but with the array having an incomplete type:

int some_array[]; // tentative

... no explicit definition, hence ...

int some_array[] = { 0 }; // this definition supplied implicitly

You see how the default sizing rule falls out of the rule
for default initialization of objects tentatively defined
but not explicitly defined? That rule wasn't written with
incomplete types in mind (I am guessing), but it has the
effect of completing them in the case of incomplete arrays.

I don't believe the normative wording actually says that, because of
a quibble about the phrase "equal to 0". I've posted to comp.std.c,
subject "Tentative array object definition".

That's good. I may have a chance to follow up there.

When writing in comp.lang.c, I try to read the Standard how
the committee reads it or expects it will be read. To me
that seems like the best fit with what comp.lang.c is for.

I know there are other ways of reading the Standard, but it
seems better to confine those to comp.std.c. That also largely
includes the meta-discussion of what the preferred reading
mode, or modes, ought to be.

I understand that you would like how the Standard is read to be
the same in comp.lang.c and comp.std.c. For now, though, let me
suggest that conversations about that are better in comp.std.c,
and for purposes of comp.lang.c it's better to read the Standard
how you think the committee reads it or expects it will be read.
Does that all make sense?
 
T

Tim Rentsch

Keith Thompson said:
Tim Rentsch said:
Keith Thompson said:
[...snip-a-lot...]
So this:

char f[];

is treated as:

char f[] = 0;

No, it would be 'char f[] = {0};' as the implementation is
obliged to do by 6.7.9p16 -- implementations are obliged to
follow "shall" directives.

Implementations are obliged to follow *all* normative requirements
in the standard. 6.9.2p2 requires an implicit "initializer equal
to 0". I wouldn't say that `{0}` is "equal to 0".

[...snip-some-more...]

Apparently we have to interpret the "initializer equal to 0" to mean
`{ 0 }` rather than `0` in this case. And we're supposed to infer
from that that `f` has exactly one element; apparently `{ 0 }` is
"equal to 0" but `{ 0, 0 }` isn't.

{ 0, 0 } is two initializers, not one.

{ 0, 0 } is one initializer, which contains two more initializers.
[...snip elaboration...]

My comments were kind of half frivolous, because I find
it hard to believe someone would take this question so
seriously, when it seems perfectly obvious what is
intended. I do think my comments have some degree of
merit (and yours also), but not sufficient to overcome
the level of silliness present (for which I am more
to blame than you).

Therefore, rather than continuing on the particular
points above, I would like to quote from Defect Report #11
(slightly reformatted):
[snip]
Response
--------
Subclause 6.7.2 External object definitions contains the
following excerpt:

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.

This statement describes an effect and not a literal token
sequence. Therefore, this example does not contain an
error.

Please note the first sentence in the last paragraph.

Interesting. That's
http://www.open-std.org/JTC1/SC22/WG14/www/docs/dr_011.html
submitted 1992-12-10 against C90; it resulted in the addition of
the footnote in question.

Personally, I'm not satisfied with the statement that it "describes
an effect and not a literal token sequence", or with the conclusion
that an initializer "equal to 0" implies that the array has 1
element. The standard isn't a mathematically formal document, but
this is one of those cases where I think it needs to be more precise.
The phrase "equal to 0" has an exact meaning; I dislike the standard
using it so loosely.

I will try to follow up soon in the comp.std.c thread.
 
B

Ben Bacarisse

Tim Rentsch said:
Ahh, now I see what you were saying.

I can see it would have been a struggle. I did not express it well.
If you'll allow me to speculate... way back when, as the
original standardization effort was under way in the late 1980's,
the rule for initializing tentative object definitions (in what
is now section 6.9.2) was done relatively early, with the wording
"with an initializer equal to 0", which appeared in C89/C90. The
fixup for non-scalar types was done later (ie after the decision
about object defintions but still part of C89). The wording from
the section on initialization (ie, in what is now 6.7.9 in C11)
that appeared in C89 is interesting:

If an object that has static storage duration is not
initialized explicitly, it is initialized implicitly as if
every member that has arithmetic type were assigned 0 and
every member that has pointer type were assigned a null
pointer constant.

It's like they wrote the two rules independently: one rule about
external object definitions that was written with scalar types in
mind, another rule in the section on initializers that was written
with non-scalar types in mind. Possibly the two sections were
written independently, or mostly independently, each side roughly
filling in the holes of the other. In any case, once the decision
about what to say for external object definitions was done, the
remaining passages were filled in focusing on non-scalar types,
and that ended up in the section on initialization.

Again, this is all speculation on my part. I did take clues from
the C89/C90 text, and also from the Rationale (C99V5.10), so
it wasn't a completely uninformed guess. More of a only very
mildly informed guess. :)

That sounds entirely plausible. If you'll permit my own speculation...
When I said "for historical reasons" I was thinking that it might be a
hang-over from B. In B, arrays are indexed from 0 but the size is one
more than the constant used in the declaration:

data[10];

makes an 11 elements array indexed from 0 to 10 inclusive. Omitting the
constants is equivalent to writing zero, so

data[];

makes data a 1-element array with a single valid index of 0. Whether
this oddity ever got into early C and then ended up being formalised
because that's what some reference implementation did I don't know; I
accept that without that link it's all a bit tentative (boom, boom).

But your explanation has the merit of being rooted in the evolution of
the words in question.
 
K

Keith Thompson

Ben Bacarisse said:
That sounds entirely plausible. If you'll permit my own speculation...
When I said "for historical reasons" I was thinking that it might be a
hang-over from B. In B, arrays are indexed from 0 but the size is one
more than the constant used in the declaration:

data[10];

makes an 11 elements array indexed from 0 to 10 inclusive. Omitting the
constants is equivalent to writing zero, so

data[];

makes data a 1-element array with a single valid index of 0. Whether
this oddity ever got into early C and then ended up being formalised
because that's what some reference implementation did I don't know; I
accept that without that link it's all a bit tentative (boom, boom).

That doesn't appear to be the case for all versions of B. I see
no such rule in <http://cm.bell-labs.com/cm/cs/who/dmr/kbman.html>.
 
K

Keith Thompson

Tim Rentsch said:
I understand that you would like how the Standard is read to be
the same in comp.lang.c and comp.std.c. For now, though, let me
suggest that conversations about that are better in comp.std.c,
and for purposes of comp.lang.c it's better to read the Standard
how you think the committee reads it or expects it will be read.
Does that all make sense?

Yes, more or less. In this particular case, though, there's a rule
that's only stated in an example, and that IMHO is not supported
by the normative text (though it could be with a small tweak).
Furthermore, it's a rule that doesn't make a whole lot of sense
to me. This raised, at least for me, a serious question about what

int i[];

as an external definition with no later completion of the type
actually *means*, and whether it's even valid. It raises issues both
about the text of the standard (clearly appropriate for comp.std.c),
and about the semantics of the language defined by the standard
(clearly appropriate for comp.lang.c).

(And "i" is a lousy name for an array!)
 
B

Ben Bacarisse

Keith Thompson said:
Ben Bacarisse said:
That sounds entirely plausible. If you'll permit my own speculation...
When I said "for historical reasons" I was thinking that it might be a
hang-over from B. In B, arrays are indexed from 0 but the size is one
more than the constant used in the declaration:

data[10];

makes an 11 elements array indexed from 0 to 10 inclusive. Omitting the
constants is equivalent to writing zero, so

data[];

makes data a 1-element array with a single valid index of 0. Whether
this oddity ever got into early C and then ended up being formalised
because that's what some reference implementation did I don't know; I
accept that without that link it's all a bit tentative (boom, boom).

That doesn't appear to be the case for all versions of B. I see
no such rule in <http://cm.bell-labs.com/cm/cs/who/dmr/kbman.html>.

Curious. Half the rule is there (the part about [] meaning [0]) but the
meaning of the constant in brackets is clearly different. In my B
reference manual (for which I have no date) it says:

"An external vector definition has one of the following forms:

name [ ] ;
name [ constant ] ;
name [ ] ival , ival ... ;
name [ constant ] ival , ival ... ;

The name is initialized with the lvalue of the base of an external
vector. If the vector size is missing, zero is assumed. In either
case, the vector is initialized with the list of ivals (See 7.1). The
actual size of the vector is the maximum of constant+1 and the number
of initial values."

and the "Tutorial Introduction to the Language B" says:

"We declare v external within the function (don't mention a size) by

extrn v;

and then outside all functions write

v[10];

External vectors may be initialized just as external simple variables:
v[10] 'hi!', 1, 2, 3, 0777; sets v[0] to the character constant 'hi!',
and V[1] through v[4] to various numbers. v[5] through v[10] are not
initialized."

which confirms the indexing is from 0 to 10 inclusive.

By the way, this is not a "two references trumps one" post as each cites
the other and the reference manual calls the tutorial "part one of this
document" so it's really all one thing.

The lack of dates is annoying but even with dates there's no easy way to
know if this is change over time or just a oddity that varied between
implementations.
 
T

Tim Rentsch

Keith Thompson said:
Tim Rentsch said:
I understand that you would like how the Standard is read to be
the same in comp.lang.c and comp.std.c. For now, though, let me
suggest that conversations about that are better in comp.std.c,
and for purposes of comp.lang.c it's better to read the Standard
how you think the committee reads it or expects it will be read.
Does that all make sense?

Yes, more or less. In this particular case, though, there's a rule
that's only stated in an example, and that IMHO is not supported
by the normative text (though it could be with a small tweak).
Furthermore, it's a rule that doesn't make a whole lot of sense
to me. This raised, at least for me, a serious question about what

int i[];

as an external definition with no later completion of the type
actually *means*, and whether it's even valid. It raises issues both
about the text of the standard (clearly appropriate for comp.std.c),
and about the semantics of the language defined by the standard
(clearly appropriate for comp.lang.c).

Oh, that may be a difference between us. As far as I'm concerned,
what happens in this case is both defined enough and clear enough
(for purposes of comp.lang.c) so that there's no question about
what's supposed to happen. I agree that the Standard could do a
better job of expressing this, but not so much that anyone who
wants to understand what semantics are dictated is likely to be
misled. Let me ask it as a question: how likely is it (in your
opinion) that someone reading the Standard will reach a wrong
conclusion about what the behavior should be in such cases?
 
K

Keith Thompson

Tim Rentsch said:
Keith Thompson said:
Tim Rentsch said:
I understand that you would like how the Standard is read to be
the same in comp.lang.c and comp.std.c. For now, though, let me
suggest that conversations about that are better in comp.std.c,
and for purposes of comp.lang.c it's better to read the Standard
how you think the committee reads it or expects it will be read.
Does that all make sense?

Yes, more or less. In this particular case, though, there's a rule
that's only stated in an example, and that IMHO is not supported
by the normative text (though it could be with a small tweak).
Furthermore, it's a rule that doesn't make a whole lot of sense
to me. This raised, at least for me, a serious question about what

int i[];

as an external definition with no later completion of the type
actually *means*, and whether it's even valid. It raises issues both
about the text of the standard (clearly appropriate for comp.std.c),
and about the semantics of the language defined by the standard
(clearly appropriate for comp.lang.c).

Oh, that may be a difference between us. As far as I'm concerned,
what happens in this case is both defined enough and clear enough
(for purposes of comp.lang.c) so that there's no question about
what's supposed to happen. I agree that the Standard could do a
better job of expressing this, but not so much that anyone who
wants to understand what semantics are dictated is likely to be
misled. Let me ask it as a question: how likely is it (in your
opinion) that someone reading the Standard will reach a wrong
conclusion about what the behavior should be in such cases?

Very likely, IMHO.

The wording in question is N1570 6.9.2p5, a non-normative example:

EXAMPLE 2 If at the end of the translation unit containing

int i[];

the array i still has incomplete type, the implicit initializer
causes it to have one element, which is set to zero on program
startup.

In the absence of that example, it would never have occurred to me that
the array i has one element. If I thought about it, I'd probably
conclude that it's equivalent to

int i[] = 0;

("with an initializer equal to 0", 6.9.2p2), and therefore a constraint
violation, or at least undefined behavior.
 
T

Tim Rentsch

Keith Thompson said:
Tim Rentsch said:
Keith Thompson said:
[...]
I understand that you would like how the Standard is read to be
the same in comp.lang.c and comp.std.c. For now, though, let me
suggest that conversations about that are better in comp.std.c,
and for purposes of comp.lang.c it's better to read the Standard
how you think the committee reads it or expects it will be read.
Does that all make sense?

Yes, more or less. In this particular case, though, there's a rule
that's only stated in an example, and that IMHO is not supported
by the normative text (though it could be with a small tweak).
Furthermore, it's a rule that doesn't make a whole lot of sense
to me. This raised, at least for me, a serious question about what

int i[];

as an external definition with no later completion of the type
actually *means*, and whether it's even valid. It raises issues both
about the text of the standard (clearly appropriate for comp.std.c),
and about the semantics of the language defined by the standard
(clearly appropriate for comp.lang.c).

Oh, that may be a difference between us. As far as I'm concerned,
what happens in this case is both defined enough and clear enough
(for purposes of comp.lang.c) so that there's no question about
what's supposed to happen. I agree that the Standard could do a
better job of expressing this, but not so much that anyone who
wants to understand what semantics are dictated is likely to be
misled. Let me ask it as a question: how likely is it (in your
opinion) that someone reading the Standard will reach a wrong
conclusion about what the behavior should be in such cases?

Very likely, IMHO.

The wording in question is N1570 6.9.2p5, a non-normative example:

EXAMPLE 2 If at the end of the translation unit containing

int i[];

the array i still has incomplete type, the implicit initializer
causes it to have one element, which is set to zero on program
startup.

In the absence of that example, it would never have occurred to me that
the array i has one element. [snip elaboration]

Yes but the example is there! That's really the point of
what I'm saying: given that the example _is_ there, I think
it's highly unlikely that anyone will be misled about what
the Standard expects should happen. Right? Or do you think
they won't notice or won't understand the example?
 
K

Keith Thompson

Tim Rentsch said:
Keith Thompson said:
Tim Rentsch said:
[...]
I understand that you would like how the Standard is read to be
the same in comp.lang.c and comp.std.c. For now, though, let me
suggest that conversations about that are better in comp.std.c,
and for purposes of comp.lang.c it's better to read the Standard
how you think the committee reads it or expects it will be read.
Does that all make sense?

Yes, more or less. In this particular case, though, there's a rule
that's only stated in an example, and that IMHO is not supported
by the normative text (though it could be with a small tweak).
Furthermore, it's a rule that doesn't make a whole lot of sense
to me. This raised, at least for me, a serious question about what

int i[];

as an external definition with no later completion of the type
actually *means*, and whether it's even valid. It raises issues both
about the text of the standard (clearly appropriate for comp.std.c),
and about the semantics of the language defined by the standard
(clearly appropriate for comp.lang.c).

Oh, that may be a difference between us. As far as I'm concerned,
what happens in this case is both defined enough and clear enough
(for purposes of comp.lang.c) so that there's no question about
what's supposed to happen. I agree that the Standard could do a
better job of expressing this, but not so much that anyone who
wants to understand what semantics are dictated is likely to be
misled. Let me ask it as a question: how likely is it (in your
opinion) that someone reading the Standard will reach a wrong
conclusion about what the behavior should be in such cases?

Very likely, IMHO.

The wording in question is N1570 6.9.2p5, a non-normative example:

EXAMPLE 2 If at the end of the translation unit containing

int i[];

the array i still has incomplete type, the implicit initializer
causes it to have one element, which is set to zero on program
startup.

In the absence of that example, it would never have occurred to me that
the array i has one element. [snip elaboration]

Yes but the example is there! That's really the point of
what I'm saying: given that the example _is_ there, I think
it's highly unlikely that anyone will be misled about what
the Standard expects should happen. Right? Or do you think
they won't notice or won't understand the example?

Sure, the example is clear enough.

I just don't think that the assertion in the example follows,
or *should* follow, from the normative text. And I wouldn't want
to rely on what it says, both because if I want a 1-element array
it's easy enough to replace "[]" by "[1]", and because I wouldn't be
astonished if some compiler, following just the normative wording,
didn't implement it that way.
 
B

Ben Bacarisse

Keith Thompson said:
Tim Rentsch said:
Keith Thompson said:
[...]
I understand that you would like how the Standard is read to be
the same in comp.lang.c and comp.std.c. For now, though, let me
suggest that conversations about that are better in comp.std.c,
and for purposes of comp.lang.c it's better to read the Standard
how you think the committee reads it or expects it will be read.
Does that all make sense?

Yes, more or less. In this particular case, though, there's a rule
that's only stated in an example, and that IMHO is not supported
by the normative text (though it could be with a small tweak).
Furthermore, it's a rule that doesn't make a whole lot of sense
to me. This raised, at least for me, a serious question about what

int i[];

as an external definition with no later completion of the type
actually *means*, and whether it's even valid. It raises issues both
about the text of the standard (clearly appropriate for comp.std.c),
and about the semantics of the language defined by the standard
(clearly appropriate for comp.lang.c).

Oh, that may be a difference between us. As far as I'm concerned,
what happens in this case is both defined enough and clear enough
(for purposes of comp.lang.c) so that there's no question about
what's supposed to happen. I agree that the Standard could do a
better job of expressing this, but not so much that anyone who
wants to understand what semantics are dictated is likely to be
misled. Let me ask it as a question: how likely is it (in your
opinion) that someone reading the Standard will reach a wrong
conclusion about what the behavior should be in such cases?

Very likely, IMHO.

The wording in question is N1570 6.9.2p5, a non-normative example:

EXAMPLE 2 If at the end of the translation unit containing

int i[];

the array i still has incomplete type, the implicit initializer
causes it to have one element, which is set to zero on program
startup.

In the absence of that example, it would never have occurred to me that
the array i has one element. [snip elaboration]

Yes but the example is there! That's really the point of
what I'm saying: given that the example _is_ there, I think
it's highly unlikely that anyone will be misled about what
the Standard expects should happen. Right? Or do you think
they won't notice or won't understand the example?

Sure, the example is clear enough.

I just don't think that the assertion in the example follows,
or *should* follow, from the normative text. And I wouldn't want
to rely on what it says, both because if I want a 1-element array
it's easy enough to replace "[]" by "[1]", and because I wouldn't be
astonished if some compiler, following just the normative wording,
didn't implement it that way.

As I understand your objection, writing [1] wouldn't help. I think
your point is that the closest reading of 6.9.2 p2 would take "with an
initializer equal to 0" to mean "= 0", but both

int x[] = 0;

and

int x[1] = 0;

are equally invalid. Such a reading would make all un-initialised
file-scope declarations of array and struct objects invalid.

This is based on an old thread you posted in comp.std.c, so maybe I've
missed some more recent postings that makes the wording of 6.9.2 p2
problematic only in more limited circumstances.
 
T

Tim Rentsch

Keith Thompson said:
Tim Rentsch said:
Keith Thompson said:
[...]
I understand that you would like how the Standard is read to be
the same in comp.lang.c and comp.std.c. For now, though, let me
suggest that conversations about that are better in comp.std.c,
and for purposes of comp.lang.c it's better to read the Standard
how you think the committee reads it or expects it will be read.
Does that all make sense?

Yes, more or less. In this particular case, though, there's a rule
that's only stated in an example, and that IMHO is not supported
by the normative text (though it could be with a small tweak).
Furthermore, it's a rule that doesn't make a whole lot of sense
to me. This raised, at least for me, a serious question about what

int i[];

as an external definition with no later completion of the type
actually *means*, and whether it's even valid. It raises issues both
about the text of the standard (clearly appropriate for comp.std.c),
and about the semantics of the language defined by the standard
(clearly appropriate for comp.lang.c).

Oh, that may be a difference between us. As far as I'm concerned,
what happens in this case is both defined enough and clear enough
(for purposes of comp.lang.c) so that there's no question about
what's supposed to happen. I agree that the Standard could do a
better job of expressing this, but not so much that anyone who
wants to understand what semantics are dictated is likely to be
misled. Let me ask it as a question: how likely is it (in your
opinion) that someone reading the Standard will reach a wrong
conclusion about what the behavior should be in such cases?

Very likely, IMHO.

The wording in question is N1570 6.9.2p5, a non-normative example:

EXAMPLE 2 If at the end of the translation unit containing

int i[];

the array i still has incomplete type, the implicit initializer
causes it to have one element, which is set to zero on program
startup.

In the absence of that example, it would never have occurred to me that
the array i has one element. [snip elaboration]

Yes but the example is there! That's really the point of
what I'm saying: given that the example _is_ there, I think
it's highly unlikely that anyone will be misled about what
the Standard expects should happen. Right? Or do you think
they won't notice or won't understand the example?

Sure, the example is clear enough.

I just don't think that the assertion in the example follows,
or *should* follow, from the normative text. And I wouldn't want
to rely on what it says, both because if I want a 1-element array
it's easy enough to replace "[]" by "[1]", and because I wouldn't be
astonished if some compiler, following just the normative wording,
didn't implement it that way.

That's a difference between us - I /would/ be astonished if any
implementation got this wrong. (That doesn't mean I would try to
convince you you shouldn't be astonished, only that my reaction
is different.)

But more important, I think my original point stands: there is
no confusion about what to tell aspiring C developers, so the
issues here are better suited for comp.std.c than comp.lang.c.
If you still disagree with that I'm unclear as to why.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,077
Messages
2,570,567
Members
47,204
Latest member
abhinav72673

Latest Threads

Top