Why is a for loop's condition optional, but a while loop's isn't? [duplicate] - c++

This question already has answers here:
Why can the condition of a for-loop be left empty? [duplicate]
(2 answers)
No loop condition in for and while loop
(5 answers)
Closed 4 years ago.
Why is for(;;) treated as an infinite loop while while() gives an error as it requires an expression? Why don't for loops expect expressions, too?

It just… doesn't.
while could have been made to permit an empty condition (which would presumably be interpreted as true), but then it would be asymmetrical with if for which this would make less sense.
Ultimately, there is no compelling reason to permit an empty condition in while preamble as any code using this would not be self-documenting.
For symmetry with for, you could require for(; true; ) — except now this looks weird because the declaration and update clauses may now be empty whereas the condition can't. Okay, let's make those mandatory too. So, what do we put in those places for no-ops? for (int dummy = 0; true; (void)dummy)? Now it's getting silly.
They're different language features and there's no strong reason to make them work the same way in this regard at the expense of other considerations.

Disclaimer: this answer explains why the syntax is valid, not why it was designed that way.
According to the documentation (emphasis mine):
formal syntax:
attr(optional) for ( init-statement condition(optional) ; iteration_expression(optional) ) statement
So all that is required is the init-statement and a ;. And for the init-statement, it says:
an expression statement (which may be a null statement ";")
So as a result, if you leave away the optional things and put a ; for the init statement, all you get is ;;.
In C it's a bit different:
for ( init_clause ; cond_expression ; iteration_expression )
loop_statement
init_clause, cond_expression, and iteration_expression are all optional
That's the two ; and three optional clauses/expressions. If you omit all three, you get ;; again.

This is a language design question, so language designers should chime in.
My opinion: the optional features (specially shortcuts) of a language should
PREVENT MISTAKES.
So, while() is easily a mistake (you omitted the conditional, eg. 0 or 1), whereas
for(;;) is rarely a mistake (you have to consciously type the 2 ;).

Related

What does C++ if-Statement with double parantheses do?

I have stumbled upon an if statement where the condition is actually an assignment and I don't really understand what it does. Now, I found a similar Question with extensive answers but I still don't quite understand, what my snippet does:
if ((x = !x))
/* some code */
The similar question I found is this one: https://unix.stackexchange.com/questions/306111/what-is-the-difference-between-the-bash-operators-vs-vs-vs
One user states, that
((…)) double parentheses surround an arithmetic instruction, that is, a computation on integers, with a syntax resembling other programming languages. This syntax is mostly used for assignments and in conditionals. This only exists in ksh/bash/zsh, not in plain sh.
What does that mean? Is the value of x toggled now and nothing else happened? In what case does this condition return false?
It does the same thing as if(x = !x) does. However, because it is very easy to accidentally use = in place of ==, compilers will warn you when you're using an assignment inside of an if statement. That warning doesn't get displayed if the assignment expression is inside of a second set of parenthesis.
So that's the point of the extra parens: to tell the compiler/reader that the writer really meant to use assignment rather than equality testing.

Odd variable assignment [duplicate]

This question already has answers here:
Uses of C comma operator [duplicate]
(20 answers)
Closed 9 years ago.
Good day, everyone.
I've come across a peculiar piece of code today, which I don't quite understand.
I don't even know how to search for this particular problem.
In this code, which works, a variable assignment is done like this:
if(condition) {
Var1 = false, Var2 = false;
}
Now, I was under the impression, that ALL commands need to be terminated by a semicolon instead of a comma. I am familiar with the syntax
Var1 = Var2 = false;
but not with the one posted above. The compiler (g++) doesn't even throw me a warning or anything...am I missing something from the specification here?
Or is the compiler generous with me and just replaces the , with a ; internally? If so, shouldn't he at least throw a warning?
Thank you for your time.
am I missing something from the specification here?
Yes, it's the "comma operator", specified by C++11 5.18. It evaluates the sub-expression to the left, then the one to the right, and the overall result is that of the right-hand one.
In this case, it's equivalent to two expression statements separated by ;
It's useful in places like if/while/for where you're only allowed one expression, but might want to do more than one thing:
while (++i, --j != 0)
and also if you like to jam multiple statements together to make life difficult for whoever has to read your code.
In the C and C++ programming languages, the comma operator (represented by the token ,) is a binary operator that evaluates its first operand and discards the result, and then evaluates the second operand and returns this value (and type). (read more)
As Alexandru Barbarosie pointed out, there's quite a thorough explanation on what's happening at https://stackoverflow.com/questions/1613230/uses-of-c-comma-operator
To quickly summarize it for whomever stumbles across this post: When used outside of for loops and stuff, the , actually has the same effect as the ;.
For more information, please visit the link.

What is the feature to use for( ;; )? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is “for(;;)” faster than “while (TRUE)”? If not, why do people use it?
Found code with this for-loop.
What exactly feature to use it insted of while(true) for example? Is it uses less memory ?
for(;;) is functionally equivalent to while(true) but avoids a "conditional expression is constant" warning with some compilers (including MSVC's cl)
This construct has been popularized by Kernighan and Ritchie in their C Programming Language book (section 3.5)
The for statement
for (expr1; expr2; expr3)
statement
If expr1 or expr3 is omitted, it is simply dropped from the expansion. If the test, expr2, is not present, it is taken as permanently true, so
for (;;) {
...
}
is an "infinite" loop, presumably to be broken by other means, such as a break or return.
There is absolutely no difference between for(;;) and while(true).
while(true)
{
}
Is always what I've used and what I've seen others use for a loop that has to be broken manually.
Some compilers are giving you wrnings that this while loom MAY be incorrect. But it is not.
The assembly code generated for both is exactly the same. No diferences.
First, The use of loop depends on the requirement & based on that only we can decide when to use which one. Just check what #Luchian has asked, then you will come to know it.
Secondly, that clearly depends on the particular implementation of the interpreter/compiler of the specific language.
That said, theoretically, any sane implementation is likely to be able to implement one in terms of the other if it was faster so the difference should be negligible at most.

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.

What's the point of issuing a compiler warning for "while(true)" and not issuing one for "for(;;)"?

When I compile C++ code with Visual C++ 9 with "warning level 4" the following:
while( true ) {
//loop body with break on certain condition
}
and the following:
for( ; true; ) {
//same loop body
}
both trigger C4127: conditional expression is constant warning but the following:
for( ; ; ) {
//same loop body
}
compiles without warning.
Why this difference, especially between the second and the third variant?
The reason for warning the user of constant conditional expressions is to help avoid bugs where the expression ends up being constant (for example, due to a typo). In the last case, there is no expression, so there is no risk of it accidentally being constant.
The reason is simple, though stupid.
It is important to diagnose infinite loop, but such might not be evident:
while(i >= 0) { --i; } // infinite if i unsigned
while(SOME_MACRO(i)) // err, depends on the expansion of macros
It is a great feature of a compiler to produce a warning for a tautological test, that is a test that turns out to be either always true or always false, because it's not obvious when it comes from a macro expansion or within a dependent context.
It just seems that VC++ pushed a bit too far here, and instead of considering tautological conditions warns for all true or false conditions it can find, even when they are already clearly stated in the code.
The for ( ;; ) construct is the canonical way to intentionally code an "endless" loop. I could imagine the compiler designers didn't want to generate a warning for that.
No point. After all, the langauge specification says ($6.5.3/2),
Either or both of the condition and
the expression can be omitted. A
missing condition makes the implied
while clause equivalent to
while(true).
So for ( ; ; ) is equivalent to while(true) even according to the Standard. Therefore, I don't see any reason why the compiler should give warning in one case but not in the other!
--
If the compiler decides to give warning, then in my opinion, the compiler should give warning when the condition is missing as opposed to when it's present, so that the warning would be interpreted as hint for programmer to mention his intention clearly and explicitly.
I mean, for ( ;; ) is more likely to be a typo than the explicit mention of condition in for ( ;true; ). The latter tells programmer's clear and explicit intent. As Steve says in comment:
For an int value y, char x = y is
equivalent to char x = (char)y, but
you might want a warning for an
implicit narrowing conversion on the
first but not the second.
So explicit intention should not receive warning, while implicit intention should receive!
Compiler warning are here to help catch potential bugs. Using an always true condition in a while loop is probably an error. For exemple, in the following code, this is probably a bug, and I'd like the compiler to warn me about it:
unsigned int x;
// ...
while (x >= 0) {
// ...
}
In such a situation, in optimized build the compiler will probably deduce that the condition is always true (since an unsigned integer cannot be smaller than 0). So there is a need for detection of an always true condition in while loop. I think that whoever wrote the detection of such an error didn't special case the while (true) case, as there is a simple way to do a infinite loop with for (;;).
You can read here, how the decision to add a warning or not in Visual Studio, is taken (the exemple are about C# but I suppose that the team has the same rule of thumb for warning in C++).