What is this "for" syntax called? [duplicate] - c++

I have seen some very weird for loops when reading other people's code. I have been trying to search for a full syntax explanation for the for loop in C but it is very hard because the word "for" appears in unrelated sentences making the search almost impossible to Google effectively.
This question came to my mind after reading this thread which made me curious again.
The for here:
for(p=0;p+=(a&1)*b,a!=1;a>>=1,b<<=1);
In the middle condition there is a comma separating the two pieces of code, what does this comma do? The comma on the right side I understand as it makes both a>>=1 and b<<=1.
But within a loop exit condition, what happens? Does it exit when p==0, when a==1 or when both happen?
It would be great if anyone could help me understand this and maybe point me in the direction of a full for loop syntax description.

The comma is not exclusive of for loops; it is the comma operator.
x = (a, b);
will do first a, then b, then set x to the value of b.
The for syntax is:
for (init; condition; increment)
...
Which is somewhat (ignoring continue and break for now) equivalent to:
init;
while (condition) {
...
increment;
}
So your for loop example is (again ignoring continue and break) equivalent to
p=0;
while (p+=(a&1)*b,a!=1) {
...
a>>=1,b<<=1;
}
Which acts as if it were (again ignoring continue and break):
p=0;
while (true) {
p+=(a&1)*b;
if (a == 1) break;
...
a>>=1;
b<<=1;
}
Two extra details of the for loop which were not in the simplified conversion to a while loop above:
If the condition is omitted, it is always true (resulting in an infinite loop unless a break, goto, or something else breaks the loop).
A continue acts as if it were a goto to a label just before the increment, unlike a continue in the while loop which would skip the increment.
Also, an important detail about the comma operator: it is a sequence point, like && and || (which is why I can split it in separate statements and keep its meaning intact).
Changes in C99
The C99 standard introduces a couple of nuances not mentioned earlier in this explanation (which is very good for C89/C90).
First, all loops are blocks in their own right. Effectively,
for (...) { ... }
is itself wrapped in a pair of braces
{
for (...) { ... }
}
The standard sayeth:
ISO/IEC 9899:1999 §6.8.5 Iteration statements
¶5 An iteration statement is a block whose scope is a strict subset of the scope of its
enclosing block. The loop body is also a block whose scope is a strict subset of the scope
of the iteration statement.
This is also described in the Rationale in terms of the extra set of braces.
Secondly, the init portion in C99 can be a (single) declaration, as in
for (int i = 0; i < sizeof(something); i++) { ... }
Now the 'block wrapped around the loop' comes into its own; it explains why the variable i cannot be accessed outside the loop. You can declare more than one variable, but they must all be of the same type:
for (int i = 0, j = sizeof(something); i < j; i++, j--) { ... }
The standard sayeth:
ISO/IEC 9899:1999 §6.8.5.3 The for statement
The statement
for ( clause-1 ; expression-2 ; expression-3 ) statement
behaves as follows: The expression expression-2 is the controlling expression that is
evaluated before each execution of the loop body. The expression expression-3 is
evaluated as a void expression after each execution of the loop body. If clause-1 is a
declaration, the scope of any variables it declares is the remainder of the declaration and
the entire loop, including the other two expressions; it is reached in the order of execution
before the first evaluation of the controlling expression. If clause-1 is an expression, it is
evaluated as a void expression before the first evaluation of the controlling expression.133)
Both clause-1 and expression-3 can be omitted. An omitted expression-2 is replaced by a
nonzero constant.
133) Thus, clause-1 specifies initialization for the loop, possibly declaring one or more variables for use in
the loop; the controlling expression, expression-2, specifies an evaluation made before each iteration,
such that execution of the loop continues until the expression compares equal to 0; and expression-3
specifies an operation (such as incrementing) that is performed after each iteration.

The comma simply separates two expressions and is valid anywhere in C where a normal expression is allowed. These are executed in order from left to right. The value of the rightmost expression is the value of the overall expression.
for loops consist of three parts, any of which may also be empty; one (the first) is executed at the beginning, and one (the third) at the end of each iteration. These parts usually initialize and increment a counter, respectively; but they may do anything.
The second part is a test that is executed at the beginning of each execution. If the test yields false, the loop is aborted. That's all there is to it.

The C style for loop consists of three expressions:
for (initializer; condition; counter) statement_or_statement_block;
The initializer runs once, when the loop starts.
The condition is checked before each iteration. The loop runs as long it evaluates to true.
The counter runs once after each iteration.
Each of these parts can be an expression valid in the language you write the loop in. That means they can be used more creatively. Anything you want to do beforehand can go into the initializer, anything you want to do in between can go into the condition or the counter, up to the point where the loop has no body anymore.
To achieve that, the comma operator comes in very handy. It allows you to chain expressions together to form a single new expression. Most of the time it is used that way in a for loop, the other implications of the comma operator (e.g. value assignment considerations) play a minor role.
Even though you can do clever things by using syntax creatively - I would stay clear of it until I find a really good reason to do so. Playing code golf with for loops makes code harder to read and understand (and maintain).
The wikipedia has a nice article on the for loop as well.

Everything is optional in a for loop. We can initialize more than one variable, we can check for more than one condition, we can iterate more than one variable using the comma operator.
The following for loop will take you into an infinite loop. Be careful by checking the condition.
for(;;)

Konrad mentioned the key point that I'd like to repeat: The value of the rightmost expression is the value of the overall expression.
A Gnu compiler stated this warning when I put two tests in the "condition" section of the for loop
warning: left-hand operand of comma expression has no effect
What I really intended for the "condition" was two tests with an "&&" between. Per Konrad's statement, only the test on to the right of the comma would affect the condition.

the for loop is execution for particular time for(;;)
the syntex for for loop
for(;;)
OR
for (initializer; condition; counter)
e.g (rmv=1;rmv<=15;rmv++)
execution to 15 times in for block
1.first initializ the value because start the value
(e.g)rmv=1 or rmv=2
2.second statement is test the condition is true or false ,the condition true no.of time execution the for loop and the condition is false terminate for block,
e.g i=5;i<=10 the condition is true
i=10;i<10 the condition is false terminate for block,
3.third is increment or decrement
(e.g)rmv++ or ++rmv

Related

C++ Single line If-Else within Loop

I read Why I don't need brackets for loop and if statement, but I don't have enough reputation points to reply with a follow-up question.
I know it's bad practice, but I have been challenged to minimise the lines of code I use.
Can you do this in any version of C++?
a_loop()
if ( condition ) statement else statement
i.e. does the if/else block count as one "statement"?
Similarly, does if/else if.../else count as one "statement"? Though doing so would become totally unreadable.
The post I mentioned above, only says things like:
a_loop()
if(condition_1) statement_a; // is allowed.
You can use ternary operator instead of if...else
while(true) return condition_1 ? a : b;
while seems redundant here if the value of its argument is always true so you can simply write
return condition_1 ? a : b;
Yes, syntactically you can do that.
if/else block is a selection-statement, which is a kind of statement.
N3337 6.4 Selection statements says:
selection-statement:
if ( condition ) statement
if ( condition ) statement else statement
switch ( condition ) statement

Fortran does if stop need an endif?

In fortran 90, does an if stop statement require a closing endif?
example:
if(foo.eq.1) stop
!do some stuff
Is do some stuff part of the loop or does stop imply endif as the program is ended?
There are mainly two places (apart from the arithmetic if) where the if keyword can be met.
Firstly it is the logical if statement
if (condition) statement_if_true
If the condition is true, the statement_if_true is executed. Anything that follows is not part of the if statement. There is no then and no end if here.
Secondly there is the if conditional construct
if (condition) then
body with statements
end if
The body can contain any number of statements or constructs and must be followed by end if. The then keyword is obligatory for the construct and the body begins on a new line after the then.

Data block Fortran 77 clarification

I am trying to access a data block, the way it is define is as follows
DATA NAME /'X1','X2','X3','X4','X5','X6','X7','X8','X9','10','11',00028650
1'12','13','14','15','16','17','18','19','20','21','22','23','24'/ 00028660
The code is on paper. Note this is an old code, the only thing i am trying to do is understand how the array is being indexed. I am not trying to compile it.
The way it is accessed is as follows
I = 0
Loop
I = I + 1
write (06,77) (NAME(J,I),J=1,4) //this is inside a write statement.
end loop //77 is a format statement.
Not sure how it is being indexed, if you guys can shed some light that would be great.
The syntax (expr, intvar=int1,int2[,int3]) widely refers to an implied DO loop. There are several places where such a thing may occur, and an input/output statement is one such place.
An implied DO loop evaluates the expression expr with the do control integer variable intvar sequentially taking the values initially int1 in steps of int3 until the value int2 is reached/passed. This loop control is exactly as one would find in a do loop statement.
In the case of the question, the expression is name(j,i), the integer variable j is the loop variable, taking values between the bounds 1 and 4. [The step size int3 is not provided so is treated as 1.] The output statement is therefore exactly like
write(6,77) name(1,i), name(2,i), name(3,i), name(4,i)
as we should note that elements of the implied loop are expanded in order. i itself comes from the loop containing this output statement.
name here may refer to a function, but given the presence of a data statement initializing it, it must somehow be declared as a rank-2 (character) array. The initialization is not otherwise important.

C++ switch statement expression evaluation guarantee

Regarding switch the standard states the following. "When the switch statement is executed, its condition is evaluated and compared with each case constant."
Does it mean that the condition expression evaluated once and once only, and it is guaranteed by the standard for each compiler?
For example, when a function is used in the switch statement head, with a side effect.
int f() { ... }
switch (f())
{
case ...;
case ...;
}
I think it is guaranteed that f is only called once.
First we have
The condition shall be of integral type, enumeration type, or class type.
[6.4.2 (1)] (the non-integral stuff does not apply here), and
The value of a condition that is an expression is the value of the
expression
[6.4 (4)]. Furthermore,
The value of the condition will be referred to as simply “the condition” where the
usage is unambiguous.
[6.4 (4)] That means in our case, the "condition" is just a plain value of type int, not f. f is only used to find the value for the condition. Now when control reaches the switch statement
its condition is evaluated
[6.4.2 (5)], i.e. we use the value of the int that is returned by f as our "condition". Then finally the condition (which is a value of type int, not f), is
compared with each case constant
[6.4.2 (5)]. This will not trigger side effects from f again.
All quotes from N3797. (Also checked N4140, no difference)
Reading N4296
Page 10 para 14:
Every value computation and side effect associated with a full-expression is sequenced before every value
computation and side effect associated with the next full-expression to be evaluated.
When I read the first line of para. 10 (above that):
A full-expression is an expression that is not a sub-expression of
another expression.
I have to believe that the condition of a switch statement is a full-expression and each condition expression is a full expression (albeit trivial at execution).
A switch is a statement not an expression (see 6.4.2 and many other places).
So by that reading the evaluation of the switch must take place before the evaluation of the case constants.
As ever many points boil down to tortuous reading of the specification to come to an obvious conclusion.
If I peer reviewed that sentence I would propose the following amendment (in bold):
When the switch statement is executed, its condition is evaluated
once per execution of the switch statement and compared with each case constant.
Yes the expression is evaluated only once when the switch statement is executed:
§ 6.4 Selection statements
4 [...] The value of a condition that is an expression is the value of the
expression [...] The value of the condition will be referred to as simply “the condition” where the usage is unambiguous.
This means that the expression is evaluated and its value is considered the condition to be evaluated against each case statement.
Section 6.4.4:
...The value of a condition that is an expression is the value of the
expression, contextually converted to bool for statements other than
switch;...The value of the condition will be referred to as simply “the condition” where the
usage is unambiguous
In my understanding, the quote above is equivalent to the following pseudo-code:
switchCondition := evaluate(expression)
Now add your quote
...its condition is evaluated and compared with each case constant.
Which should be translated to:
foreach case in cases
if case.constant == switchCondition
goto case.block
So yeah, it looks like this is the case.
Does this code print hello once or twice?
int main() {
printf("hello\n");
}
Well, I think the answer is in the more general understanding of what the standard describes rather than in the specific switch statement wording.
As per Program execution [intro.execution] the standard describes the behaviour of some abstract machine that executes the program parsed according to the C++ grammar. It does not really define what 'abstract machine' or 'executes' mean, but they are assumed to mean their obvious computer science concepts, i.e. a computer that goes through the abstract syntax tree and evaluates every part of it according to the semantics described by the standard. This implies that if you wrote something once, then when the execution gets to that point, it is evaluated only once.
The more relevant question is "when the implementation may evaluate something not the way written in the program"? For this there is the as-if rule and a bunch of undefined behaviours which permit the implementation to deviate from this abstract interpretation.
This issue was clarified for C++ '20 making it clear that the condition is evaluated once:
When the switch statement is executed, its condition is evaluated. If one of the case constants has the same value as the condition, control is passed to the statement following the matched case label.
The commit message for the change acknowledges that it was potentially confusing before:
[stmt.switch] Clarify comparison for case labels
The expression is guaranteed that is evaluated only once by the flow of control. This is justified in the standard N4431 §6.4.2/6 The switch statement [stmt.switch] (Emphasis mine):
case and default labels in themselves do not alter the flow of
control, which continues unimpeded across such labels. To exit from a
switch, see break, 6.6.1. [ Note: Usually, the substatement that is
the subject of a switch is compound and case and default labels appear
on the top-level statements contained within the (compound)
substatement, but this is not required. Declarations can appear in the
substatement of a switch-statement. — end note ]

Why can the condition of a for-loop be left empty? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
No loop condition in for and while loop
Why is the condition in a for-loop allowed to be left empty? For example
for (;;)
compiles fine. Why does this empty expression evaluate to true but the following
if () {}
while () {}
will both fail? I want to know if/why the for-loop is an exception to this case.
http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf
These are the iteration statements
while ( expression ) statement
do statement while ( expression ) ;
for ( expression [opt] ; expression [opt] ; expression [opt] ) statement
for ( declaration expression [opt] ; expression [opt] ) statement
The while loop was designed to evaluate the controlling expression before each execution of the loop and the do loop was designed to evaluate after each execution.
The for loop was designed as a more sophisticated iteration statement.
6.8.5.3 The for statement
The statement
for ( clause-1 ; expression-2 ; expression-3 ) statement
behaves as follows: The
expression expression-2 is the controlling expression that is
evaluated before each execution of the loop body. The expression
expression-3 is evaluated as a void expression after each execution of
the loop body. If clause-1 is a declaration, the scope of any
identifiers it declares is the remainder of the declaration and the
entire loop, including the other two expressions; it is reached in the
order of execution before the first evaluation of the controlling
expression. If clause-1 is an expression, it is evaluated as a void
expression before the first evaluation of the controlling expression.
Both clause-1 and expression-3 can be omitted. An omitted
expression-2 is replaced by a nonzero constant.
The specification allows expression-2, the condition of the loop, to be omitted and is replaced by a nonzero constant. This means that the for loop will continue to execute indefinitely.
This is useful for allowing a simple syntax for iterating with no end.
for(int i = 0;;i++) { //do stuff with i }
That's much simpler to write and understand than writing a while(1) loop with a variable declared outside the loop and then incremented inside the loop.
The for loop specification then goes on to allow you to omit clause-1 so that you can declare or initialize variables elsewhere, and you can omit expression-3 so that you are not required to evaluate any expression upon completion of each loop.
The for loop is a special case. The while loop and the do loop are strict and require an expression, but the for loop is a flexible iteration statement.
I can't give a definitive answer, but my guess would be that it's because in the for loop case, there are three different expressions, each of which you may or may not need to use depending on the loop.
In the if case, it would make no sense if there were no expression; it would need to always act as if the expression were true or false, and thus be equivalent to just one of the clauses alone. In the while case, there would be a meaningful interpretation of while () { }, which would be to evaluate to while (1) { } (giving you a loop that you can break out of with break), but I guess that the benefits of leaving out that single character are not worth the trouble.
However, in the for loop case, there are three different expressions, each of which may or may not be needed. For instance, if you want to initialize and increment something on every loop, but will use break to break out of the loop, you can write for (i = 0; ; ++i), or if you just want the test and increment, because your variable is already initialized, you could write for (; i > 0; --i). Given that each of these expressions may not be necessary depending on your loop, making you fill in a placeholder for all that you do not use seems a bit cumbersome; and for consistency, rather than requiring a placeholder in one of them, all of them are optional, and the condition is considered to be a constant non-zero value if omitted.
Of course, it is sometimes easy to read too much intent into a design decision. Sometimes, the reason for a given standard is simply that that's how it was implemented in the first implementation, and everyone else just copied that. For an example, see Rob Pike's explanation of why files starting with . are hidden in Unix; it wasn't due to a deliberate design decision, but simply because someone took a shortcut when writing ls and didn't want to display the . and .. directory entries every time.