Modelling "if" with "for" - c++

Shouldn't the following code work mostly like an "if( condition )" statement, up to the obvious misbehaviour when it's inside another loop and the "body" has its own break or continue statements:
for( ; condition ; break ) {
body;
}
This was triggered by a coffee break chat on C++ syntax regarding the assumption that
for( init ; condition ; update ) {
body;
}
is identical to
{
init;
while( condition ) {
body;
update;
}
}
A quick experiment with g++ shows that modelling "if(condition)" with "for(;condition;break)" doesn't compile. So the question is: according to the latest standards, should g++ swallow such construction or is it correct in rejecting it?

It's correct to reject it - the for loop is in the form (see ISO C++ §6.5.3):
for ( for-init-statement condition opt ; expression opt) statement
A break is a statement, not an expression.
As mentioned, the workaround is
for( ; condition ; ) {
body;
break;
}
Here's another way without using break:
bool b = false;
for (; condition && !b++; ) { // this usage of operator++ on bool is deprecated
body
}

This is not valid C++, the draft C++ standard in section 6.6.1 The break statement says (emphasis mine):
The break statement shall occur only in an iteration-statement or a switch statement and causes termination of the smallest enclosing iteration-statement or switch statement; control passes to the statement following the terminated statement, if any.
and we can see from the grammar of for from section 6.5 Iteration statements here:
for ( for-init-statement conditionopt; expressionopt) statement
^^^^^^^^^
the statement is the body of the for loop.
EDIT
As dasblinkenlight corrected me, this is not strong enough for the general case. We need to observe that break is a statement not an expression and therefore can not be in the header of a for loop.

It is correct in rejecting it. break cannot be outside the block of code which constitutes the body of the loop itself. That code is not valid C++.

break should be in the body of the for loop:
for( ; condition ; ) {
body;
break;
}

The syntax of a for statement is:
for ( for-init-statement condition[opt] ; expression[opt] ) statement
So the update clause must be an expression, and break not an expression.

Related

Is "else if" a single keyword?

I am new to C++. I often see conditional statement like below:
if
statement_0;
else if
statement_1;
Question:
Syntactically, shall I treat else if as a single keyword? Or is it actually an nested if statement within the outer else like below?
if
statement_0;
else
if
statement_1;
They are not a single keyword if we go to the draft C++ standard section 2.12 Keywords table 4 lists both if and else separately and there is no else if keyword. We can find a more accessible list of C++ keywords by going to cppreferences section on keywords.
The grammar in section 6.4 also makes this clear:
selection-statement:
if ( condition ) statement
if ( condition ) statement else statement
The if in else if is a statement following the else term. The section also says:
[...]The substatement in a selection-statement (each substatement, in the
else form of the if statement) implicitly defines a block scope (3.3).
If the substatement in a selection-statement is a single statement and
not a compound-statement, it is as if it was rewritten to be a
compound-statement containing the original substatement.
and provides the following example:
if (x)
int i;
can be equivalently rewritten as
if (x) {
int i;
}
So how is your slightly extended example parsed?
if
statement_0;
else
if
statement_1;
else
if
statement_2 ;
will be parsed like this:
if
{
statement_0;
}
else
{
if
{
statement_1;
}
else
{
if
{
statement_2 ;
}
}
}
Note
We can also determine that else if can not be one keyword by realizing that keywords are identifiers and we can see from the grammar for an identifier in my answer to Can you start a class name with a numeric digit? that spaces are not allowed in identifiers and so therefore else if can not be a single keyword but must be two separate keywords.
Syntactically, it's not a single keyword; keywords cannot
contain white space. Logically, when writing lists of else
if, it's probably better if you see it as a single keyword,
and write:
if ( c1 ) {
// ...
} else if ( c2 ) {
// ...
} else if ( c3 ) {
// ...
} else if ( c4 ) {
// ...
} // ...
The compiler literally sees this as:
if ( c1 ) {
// ...
} else {
if ( c2 ) {
// ...
} else {
if ( c3 ) {
// ...
} else {
if ( c4 ) {
// ...
} // ...
}
}
}
but both forms come out to the same thing, and the first is far
more readable.
No, it is not.
They are two keywords and, moreover, the second "if" is a substatement "inside" the scope determined by the first "else" statement.
You can see the scope by using curly braces:
if(X) {
statement_0;
}
else {
if(Y) {
statement_1;
}
}
And normally implemented with two distinct keywords, one is if and one is else.
As already answered, it isn't. They are two keywords. It's start of two statements one following each one other. To try make it a bit more clear, here's the BNF gramar which deal with if and else statements in C++ language.
statement:
labeled-statement
attribute-specifier-seqopt expression-statement
attribute-specifier-seqopt compound-statement
attribute-specifier-seqopt selection-statement
attribute-specifier-seqopt iteration-statement
attribute-specifier-seqopt jump-statement
declaration-statement
attribute-specifier-seqopt try-block
selection-statement:
if ( condition ) statement
if ( condition ) statement else statement
Note that statement itself include selection-statement. So, combinations like:
if (cond1)
stat
else if(cond2)
stat
else
stat
are possible and valid according to C++ standard/semantics.
Note: C++ grammar take from this page.
else and if are two different C++ keywords. An if statement can be followed by an optional else if...else statement. An if statement can have zero or more else if's and they must come before the else.
You can find syntax and example in this if...else statement tutorial
I would just like to add my point of view to all these explanations. As I see it, if you can use these keywords separately, they must be TWO keywords.
Maybe you can have a look at c++ grammar, from this link in stackoverflow:
Is there a standard C++ grammar?
Regards
An if statement can be followed by an optional else if...else statement, which is very useful to test various conditions using single if...else if statement.
When using if , else if , else statements there are few points to keep in mind.
An if can have zero or one else's and it must come after any else if's.
An if can have zero to many else if's and they must come before the else.
Once an else if succeeds, none of he remaining else if's or else's will be tested.
have a look if...else statement tutorial.

Convincing a colleague about their if not being nested

One of my university colleagues, who has started programming this year, sometimes writes if statements like this:
if(something) doA();
else
if(something2) doC();
else doD();
He is conviced that the second if-else pair is treated as a single entity, and that it is in fact nested under the first else.
I'm, however, sure that his code is equivalent to:
if(something) doA();
else if(something2) doC();
else doD();
This shows that the second else is not actually nested, but on the same level as the first if. I told him he needs to use curly braces to achieve what he wants to.
"But my code works as intended!"
And indeed, it worked as intended. Turns out the behavior of the code was the same, even if the else was not nested.
Surprisingly, I have found myself unable to write a clear and concise example that shows different behavior between
if(something) doA();
else
if(something2) doC();
else doD();
and
if(something) doA();
else {
if(something2) doC();
else doD();
}
Can you help me find an example that will show my colleague the difference between using/not using curly braces?
Or is the incorrect-looking version always equivalent to the one with curly braces, in terms of behavior?
Per C 2011 6.8.4 1, the grammar for a selection-statement includes this production:
selection-statement: if ( expression ) statement else statement
Per 6.8 1, a production for statement is:
statement: selection-statement
Thus, in:
if(something) doA();
else
if(something2) doC();
else doD();
the indented if and else form a selection-statement that is the statement that appears in the else clause of the preceding selection-statement.
The productions I have shown show that this is a possible interpretation in the C grammar. To see that it is the only interpretation, we observe that the text in the else clause of the initial selection-statement must be a statement, because there is no other production in the C grammar that produces an else keyword. (This is most easily seen by searching the grammar in clause A.2. Due to its size, I will not reproduce it here.) So we know the else is followed by a statement. We can easily see that the statement is a selection-statement, since it begins with if. Then the only question remaining is whether the next else is part of that if statement or not. Per 6.8.4.1 3, “An else is associated with the lexically nearest preceding if that is allowed by the syntax.”
Both structures come out to the same thing. The compiler
effectively sees the code as:
if ( something ) {
doA()
} else {
if ( something2 ) {
doC();
} else {
doD();
}
}
In practice, however, there is no different between this and:
if ( something ) {
doA();
} else if ( something2 ) {
doC();
} else {
doD();
}
The extra braces encapsulate a single statement, and you don't
actually need the braces when the if or the else controls
a single statement. (My first example puts every statement
except the encompassing if in braces.)
Logically, programmers tend to thing along the lines of the
second; languages where some sort of bracing ({},
BEGIN/END or indentation) is required almost always add an
elsif or elif keyword in order to permit this second form.
C and C++ (and Java, and C#, and...) don't, because the second
form works out without the extra keyword.
In the end, you don't want the extra indentation. (I've cases
with fifteen or twenty successive else if. That would make
for some serious indentation.) On the other hand, you do want
the controlled statement on a separate line. (Bracing is
optional: if your coding standard puts the brace on a separate
line, it's also conventional to suppress it if it only contains
a single statement.)

C++ if Followed by a for Loop block

I remember once I've seen somebody writing C++ code like this:
if (something is true)
for (int i = 0; i < max; i++) {
//do something
line 1;
line 2;
line 3;
....
....
}
else
....
It works the same as the following code:
if (something is true) { //note the bracket here
for (int i = 0; i < max; i++) {
//do something
line 1;
line 2;
line 3;
....
....
}
}
else
....
I'm wondering if the compiler treated the for loop block as one line nested within the if clause? Can the multiple lines of code within bracket always be treated as one line? I can't quite understand how does the compiler parse and analyse this.
This is indeed correct code, although it may easily confuse readers. The if-statement considers the first following statement as it's then statement. Code between {} is usually considered a block or compound statement, containing the statements within it. Similarly, the for statement is considered one statement, including the loop body, which is the first statement to follow it (and can again be a block).
They are not really "lines" but rather statements. For instance your
line 1;
line 2;
line 3;
could be rewritten as and would be just as valid as:
line 1; line 2; line 3;
So the compiler is not really looking at lines but rather statements.
A single statement as defined by the grammar is considered either (somewhat simplified):
1) a simple statement terminated by a semicolon (as above)
OR
2) as a statement-block which is one or more simple statements enclosed within brackets {}.
Your first case runs fine because the if statement without brackets considers the next single statement(for loop)as a part of its body to be executed. The body of the for loop is a part of the loop itself.
If there had been no brackets for the loop itself, then only the first statement of the loop would have been executed.
{} defines a compound statement or block.
With the introduction of control structures we are going to have to
introduce a new concept: the compound-statement or block. A block is a
group of statements which are separated by semicolons (;) like all C++
statements, but grouped together in a block enclosed in braces: { }:
From cplusplus.com: Control Structures
The if control structure is defined as follows:
if (condition) statement
That statement can be defined as a single instruction/statement, or a compound statement. Either way, it's the next statement to be executed.
for (;;) statement is a special type of control structure called an iteration structure.
Therefore,
//The control structure is going to apply to the next statement
if (condition)
for (;;) //This for loop is the next statement. It applies to the next statement.
{
//The next statement is a compound statement.
}
Yes if there are no brackets after the if-statement it will just process the next line if the conditions are true. Since the next line was a for statement, it treats it as one command.

C++: Short question regarding switch and break

Example:
switch( x )
{
case y:
if ( true )
{
break;
}
cout << "Oops";
break;
}
If the switch statement selects y, will Oops be written to the standard output?
- Is break in switch statements a dynamic keyword like continue which can be called under conditions or static like a closing bracket }?
break breaks out of an enclosing switch, while, for, or do ... while. It doesn't break out of an enclosing if or bare block. Pretty much exactly like continue.
It's certainly not part of the required syntax of a switch statement (like a close-brace is part of the syntax of blocks). break is a statement, essentially meaning "transfer execution to the point after the end of the innermost breakable construct".
No, Oops will not written out, the break jumps behind this statement.
You can use break statements conditionally just fine, you only have to watch out when you create nested statements that also support break (i.e. loops).
break is absolutely dynamic. So, if you write if (false) break; your Oops would be written out.
Think of break in this case as a goto end_of_switch.
No, it will not be printed in your case. break only breaks from switches and loops, not conditionals or functions or arbitrary enclosing scopes. Therefore, a more relevant question would be whether Oops is printed in this case:
switch( x )
{
case y:
for ( int i = 0; i < 10; ++i )
{
break;
}
cout << "Oops";
break;
}
And the answer here is yes, it will. The break will break out of the for, not the switch.
No. It would break out of the switch construct. "break" is used to come out of the innermost loop construct or switch construct. So, in your case the "oops" is not printed out on the screen. If you want that to happen, in your code, you could use if(false) instead of if(true).

In C/C++ why does the do while(expression); need a semi colon?

My guess is it just made parsing easier, but I can't see exactly why.
So what does this have ...
do
{
some stuff
}
while(test);
more stuff
that's better than ...
do
{
some stuff
}
while(test)
more stuff
Because you're ending the statement. A statement ends either with a block (delimited by curly braces), or with a semicolon. "do this while this" is a single statement, and can't end with a block (because it ends with the "while"), so it needs a semicolon just like any other statement.
If you take a look at C++ grammar, you'll see that the iteration statements are defined as
while ( condition ) statement
for ( for-init-statement condition-opt ; expression-opt ) statement
do statement while ( expression ) ;
Note that only do-while statement has an ; at the end. So, the question is why the do-while is so different from the rest that it needs that extra ;.
Let's take a closer look: both for and regular while end with a statement. But do-while ends with a controlling expression enclosed in (). The presence of that enclosing () already allows the compiler to unambiguously find the end of the controlling expression: the outer closing ) designates where the expression ends and, therefore, where the entire do-while statement ends. In other words, the terminating ; is indeed redundant.
However, in practice that would mean that, for example, the following code
do
{
/* whatever */
} while (i + 2) * j > 0;
while valid from the grammar point of view, would really be parsed as
do
{
/* whatever */
} while (i + 2)
*j > 0;
This is formally sound, but it is not really intuitive. I'd guess that for such reasons it was decided to add a more explicit terminator to the do-while statement - a semicolon. Of course, per #Joe White's answer there are also considerations of plain and simple consistency: all ordinary (non-compound) statements in C end with a ;.
It's because while statements are valid within a do-while loop.
Consider the different behaviors if the semicolon weren't required:
int x = 10;
int y = 10;
do
while(x > 0)
x--;
while(x = y--);
While I don't know the answer, consistency seems like the best argument. Every statement group in C/C++ is either terminated by
A semicolon
A brace
Why create a construct which does neither?
Flow control statement consistency
Considering consistency...
if (expr) statement;
do statement; while (expr);
for (expr; expr; expr) statement;
while (expr) statement;
...all these flow-control constructs, end with a semicolon.
But, countering that we can note that of the block-statement forms, only do while is semicolon delimited:
if (expr) { ... }
do { ... } while (expr);
for (expr; expr; expr) { }
while (expr) { }
So, we have ';' or '}', but never a "bare" ')'.
Consistency of statement delimiters
We can at least say that every statement must be delimited by ; or }, and visually that helps us distinguish statements.
If no semicolon were required, consider:
do statement1; while (expr1) statement2; do ; while (expr2) statement3; while (expr3) statement4;
It's very difficult to visually resolve that to the distinct statements:
do statement1; while (expr1)
statement2;
do ; while (expr2)
statement3;
while (expr3) statement4;
By way of contrast, the following is more easily resolved as a ; immediately after a while condition tells you to seek backwards for the do, and that the next statement is unconnected to that while:
do statement1; while (expr1); statement2; do ; while (expr2); statement3; while (expr3) statement4;
Does it matter, given people indent their code to make the flow understandable? Yes, because:
people sometimes make mistakes (or have them transiently as the code's massaged) and if it visually stands out that means it will be fixed more easily, and
macro substitutions can throw together lots of statements on one line, and we occasionally need to visually verify the preprocessor output while troubleshooting or doing QA.
Implications to preprocessor use
It's also worth noting the famous preprocessor do-while idiom:
#define F(X) do { fn(X); } while (false)
This can be substituted as follows:
if (expr)
F(x);
else
x = 10;
...yields...
if (expr)
do ( fn(x); } while (false);
else
x = 10;
If the semicolon wasn't part of the do while statement, then the if statement would be interpreted as:
if (expr)
do-while-statement
; // empty statement
else
x = 10;
...and, because there are two statements after the if, it's considered complete, which leaves the else statement unmatched.
C is semicolon-terminated (whereas Pascal is semicolon-separated). It would be inconsistent to drop the semicolon there.
I, frankly, hate the reuse of the while for the do loop. I think repeat-until would have been less confusing. But it is what it is.
In C/C++ whitespace don't contribute to structure (like e.g. in python). In C/C++ statements must be terminated with a semicolon. This is allowed:
do
{
some stuff; more stuff; even more stuff;
}
while(test);
My answer is that, the compiler may get confusion, when we didn't include the semicolon in the termination of do.....while(); loop. Without this it is not clear about:
when the do ends?
If the while may a separate loop followed immediately after do loop.
That's why we include semicolon in the end of do......while loop, to indicate the loop is terminating here if the condition is false.