K
Keith Thompson
luserXtrog said:Eric Sosman said:luserXtrog wrote: [...]
How did you find those sections without reading any of the surrounding
material? Everything is a statement.Nonsense. `int i = 42;', for example, is not a statement.
`int main(void) { return 0; }' is not a statement.
I explicitly mentioned function definitions as another case entirely.
You have not been paying attention.
Sure he has. You said "Everything is a statement", which you later
said was a deliberate exaggeration, but that wasn't obvious at the
time. He simply provided two counterexamples. You were speaking
figuratively, and he took it literally. It's not a big deal.
Incidentally, given
int main(void) { return 0; }
the whole thing is not a statement, but both
return 0;
and
{ return 0; }
*are* statements. The latter may seem surprising, but the syntax for
a function-definition includes a compound-statement. (It *could*
have used "statement" rather than "compound-statement", making
int main(void) return 0; /* not legal C! */
legal, but it didn't, so it isn't.
Section 6.8.2, entitled "Compound statement", describes how a block
may be used wherever a statement is required.6.8.2p1 gives the syntax of a compound statement, and 6.8.p2 says
in its entirety "A compound statement is a block," and that's all there
is in 6.8.2. Where is the description you, er, describe?"A compound statement is a block" does not imply that all blocks are
compound statements. For example, `if (a) b=42; else c=24;' has three
blocks, none of them compound statements (6.8.4p3).
You're right. I've always assumed that "block" and "compound
statement" are synonymous, but they're not. But I dislike the way the
standard expresses this.
[big snip]
What's the point? Certain declarations have block scope, but you
can only have a declaration within a compound statement anyway; this:
if (x == 3)
int y;
is illegal. (That's not quite true; a for statement can have a
declaration.)
Which is just some bullshit adopted from C++. not C90. not portable.
This is the oddditty. Not the other way 'round.
If you don't like it, that's fine, but there's no need to get upset
about it. Personally I think it's a very nice feature, though I do
tend to avoid using it in C because support for C99-specific features
isn't universal.
I don't ever understand that question.
It seems like you guys are operating with some conceptual model that
shoots straight to some virtual machine assembler listing, where the
blocks have nice rectangular borders around them. I think you need to
dwell in the abstract syntax tree a little more.
You seem to be mining the footnotes. I think you need to look at the
pictures more. In the grammar it's all about statements. Statement
this; statement that; conditional statement; iterative statement.
The word 'block' is your block.
My question was specifically about the word "block". I honestly have
no idea what you're trying to say here.
I just checked the C90 standard; C90 6.6.2 says:
A _compound statement_ (also called a _block_) allows a set of
statements to be grouped into one syntactic unit, which may have
its own set of declarations and initializations (as discussed in
6.1.2.4). The initializers of objects that have automatic storage
duration are evaluated and the values are stored in the objects in
the order their declarators appear in the translation unit.
So in C90, "block" and "compound statement" were synonymous; this was
a change from C90 to C99.
Checking the C99 Rationale (something I should have done sooner), I
see that it answers my question. You can't have an explicit
declaration in any context where the expansion of what constitutes a
block makes any difference, but you can have an implicit one. A
compound literal (a new C99 feature) creates an implicit object with
automatic storage duration associated with the enclosing block;
attempting to access that object after the block terminates invokes
undefined behavior. (A compound literal outside any function creates
an implicit object with static storage duration.) If, for example,
the substatements of an if statement were not treated as blocks, then
this:
{
if (condition)
/* single statement using a compound literal */
else
/* single statement using a compound literal */
/* code that refers to the object */
}
would have well-defined behavior, because the implicit objects
would have the scope of the enclosing compound statement, but this:
{
if (condition) {
/* single statement using a compound literal */
}
else {
/* single statement using a compound literal */
}
/* code that refers to the object */
}
would have undefined behavior, because the object would vanish as the
end of the *inner* compound statement. It's common (but not
universal) practice to use compound statements for all selection and
iteration statements; here we'd have a case where adding braces would
introduce undefined behavior.
The solution chosen by the committee was to treat the single
statements as blocks, which means you have undefined behavior either
with or without the added braces. At least it's consistent.
For more details including a more complete example and a marvelously
obscure quiet change, see section 6.8 of the C99 Rationale,
<http://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf>.