While I am reading in a code, I found that the loop for was used with just two arguments (the one in the middle is absent). When the program is executed, the loop for is infinite. Here is a minimal working environment. Could anyone tell what is wrong in the code?
// Example program
#include <iostream>
using namespace std;
int main()
{
for (int i = 0; ; i = (i+1)%2)
{
cout << i << endl;
}
}
when you have
for (statement 1;statement 2;statement 3){}
statement 1: performs at entry to the for loop
statement 2: is checked before every new iteration, if it evaluates as 0/false it doesn't continue
statement 3: is performed at end of every iteration regardless.
if you leave statement 2 empty it default to true/1 and so every time it loops it will evaluate as continuing and so will be an infinite loop
There's nothing wrong with the code, it's doing exactly what you told it to do.
The second section of the if statement is the continuation condition which, if omitted, defaults to true.
In fact, you can leave out any combination of the loop initialisation, continuation condition and post-iteration sections and they will default to, respectively:
no initialisation.
continue forever (in the absence of control flow statements like break).
no post-iteration actions.
which is why:
for (;;)
is a perfectly valid infinite loop.
This is explained in the C standard. §6.8.5.3:
1 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. [..]
2 Both clause-1 and expression-3 can be omitted. An omitted
expression-2 is replaced by a nonzero constant.
That essentially means that it will repeat forever.
A further explanation continues in a footnote (which is considered non-normative):
158) 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.
There is nothing wrong with the code. This allows infinite counting (to an int's limit that is) until an internal condition stops it. None of the three parts of a for loop are necessary, thus any of the below are valid.
for(;;); // Yes, this will never stop
for(int x = 0;;){
}
for(int x = 0; x < 10; ++x);
for(; someCondition != true;){}
And so on, all parts are optional, even the body.
A reason this might be used would be that if one thing is done with the data, I need to stop, but if another thing, I want to do something with it. However, at the same time, I need to know how many times it's happened. You'll use it without all the parameters eventually, but for now, just understand that to have a valid for loop, all you have to have is the top line in my code snippet above.
The syntax for a for loop in C++ is:
for ( init; condition; increment )
{
//statement(s) to be executed while the condition is true
}
See here for more details: http://www.tutorialspoint.com/cplusplus/cpp_for_loop.htm
Your prgram missed the condition statement. Therefore, the for loop repeated forever.
Related
so i had this segment of code in my C++ test today:
for(int i=10;i++;i<15){cout<<i;}
what is this supposed to output? and why ?
Thanks!
A for loop will run until either:
its 2nd argument evaluates as 0/false.
the loop body calls break or return, or throws an exception, or otherwise exits the calling thread.
The code you have shown may or may not loop indefinitely. However, it will not loop the 5 times you might be expected, because the 2nd and 3rd arguments of the for statement are reversed.
The loop should look like this:
for(int i = 10; i < 15; i++)
However, in the form you have shown:
for(int i = 10; i++; i < 15)
The loop will continue running as long as i is not 0. Depending on how the compiler interprets i++ as a loop condition, it may recognize that this will lead to overflow and just decide to ignore i and make the loop run indefinitely, or it may actually increment i and let overflow happen.
In the latter case, on every loop iteration, i will be incremented, and eventually i will overflow past the maximum value that an int can hold. At that time, i will usually wrap around to a negative value, since int is a signed type (though overflow behavior is not officially defined by the C++ standard, so the wrap is not guaranteed). Then the loop will keep running since i is not 0, incrementing i each time until it eventually reaches 0, thus breaking the loop.
In either case, the loop will end up calling cout << i many thousands/millions of times (depending on the byte size of int), or call it forever until the program is terminated.
what is this supposed to output? and why ?
That unconditionally do an signed int overflow.
So it is is Undefined behavior and can do anything.
For practical purposes, with any modern compiler this loop will continue forever. The reason for that is that the code is syntactically correct (however very incorrect semantically).
for(int i = 10; i++; i < 15)
means: start with i equal to 10. Check if i++ is true (which it will be, since integers are convertible to booleans, with non-0 values converted to true). Proceed with loop body, on every iteration performing comparison of i and 15 (just comparing, not checking the result, this is your increment expression), incrementing i and checking if it is non-0.
Since compilers understand that signed integers never overflow, i++ could never go to 0 when started with 10. As a result, optimizing compiler will remove the check altogether, and turn it into infinite loop.
Last, but not the least, learn to love compiler warnings. In particular, this code produces following:
<source>:4:29: warning: for increment expression has no effect [-Wunused-value]
for (int i = 10; i++; i < 15) {
~~^~~~
<source>:4:23: warning: iteration 2147483637 invokes undefined behavior [-Waggressive-loop-optimizations]
for (int i = 10; i++; i < 15) {
~^~
<source>:4:23: note: within this loop
for (int i = 10; i++; i < 15) {
^~
This question already has answers here:
Why do for(;;) loops behave like infinite loops?
(2 answers)
Closed 5 years ago.
I've written infinite loops like this numerous times over the years in both C and C++, but today is the first time I really thought about it -- why is it an infinite loop when the condition clause is empty? One would expect you'd have to write something like for(;true;); to get a valid infinite loop?
while(); doesn't compile nor does while(;);
Anyways, I like the for(;;); syntax and use it often, but is it a special case to treat an empty condition block as true or are there other cases in C or C++ where an empty condition expression is interpreted as true?
The C Standard explicitly describes this behavior of for loops:
C11 Draft Standard §6.8.5.3 2
Both clause-1 and expression-3 can be omitted. An omitted expression-2
is replaced by a nonzero constant.
Similarly, for C++:
C++14 Draft Standard §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).
The behaviors are defined by the language (C++). For the for loop, the condition part is optional:
Syntax
formal syntax:
attr(optional) for ( init-statement condition(optional) ; iteration_expression(optional) ) statement
and (emphasis mine)
The above syntax produces code equivalent to:
{
init_statement
while ( condition ) {
statement
iteration_expression ;
}
}
Except that
3) Empty condition is equivalent to while(true)
For while loop, the condition part is necessary, it can't be ommitted.
Syntax
attr(optional) while ( condition ) statement
Is it possible to do the following without getting a stackoverflow?
int foo(int i = 0)
{
return foo(--i) || i;
}
When foo(--i) evaluates to 0, it should return false, therefore returning i and ending the execution.
You want return !i || foo(--i).
Note that || is short-circutted. This means that evaluation (which is performed from left to right) will continue for only as long as the result of the expression is not known. So the way I've written it, the case i being zero will block the recursion.
(Moving on to more advanced issues, you need to be very careful when evaluating expressions when the same variable appears in more than one sub-expression and it's value is changed in some of them. My having !i and --i could get me in trouble: I'm not too far away from undefined behaviour here. In fact, it turns out that my code is completely safe since || is a sequence point and the order of evaluation with || is well-defined. But do be careful.)
From what you have coded foo never returns because it will continuosly go on decreasing i and recurse. You need a check inside foo which returns whatever you want when you get i as 0.
A question from a job-interview
int count = 0;
void func1()
{
for ( int i =0 ; i < 10; ++i )
count = count + 1;
}
void func2()
{
for ( int i =0 ; i < 10; ++i )
count++;
}
void func3()
{
for ( int i =0 ; i < 10; ++i )
++count;
}
int main()
{
thread(func1);
thread(func2);
thread(func3);
//joining all the threads
return 0;
}
The question is: what's the range of values count might theoreticaly take? The upper bound apparently is 30, but what's the lower one? They told me it's 10, but i'm not sure about it. Otherwise, why do we need memory barriers?
So, what's the lower bound of the range?
It's undefined behavior, so count could take on any value
imaginable. Or the program could crash.
James Kanze's answer is the right one for all practical purposes, but in this particular case, if the code is exactly as written and the thread used here is std::thread from C++11, the behavior is actually defined.
In particular, thread(func1); will start a thread running func1. Then, at the end of the expression, the temporary thread object will be destroyed, without join or detach having been called on it. So the thread is still joinable, and the standard defines that in such a case, the destructor calls std::terminate. (See [thread.thread.destr]: "If joinable() then terminate(), otherwise no effects.") So your program aborts.
Because this happens before the second thread is even started, there is no actual race condition - the first thread is the only one that ever touches count, if it even gets that far.
Starting with the easy part, the obvious upper bound is 30 since, if everything goes right, you have 3 calls to functions; each capable of incrementing count 10 times. Overall: 3*10=30.
Ad to the lower bound, they are correct and this is why - the worst-case scenario is that each time that one thread tries to increment count, the other threads will be doing so at exactly the same time. Keeping in mind that ++count actually is the following pseudo code:
count_temp = count;
count_temp = count_temp+1;
count = count_temp;
It should be obvious that if they all perform the same code at the same time, you have only 10 real increments, since they all read the same initial value of count and all write back the same added value.
First of all, I'd like to thank you guys for giving me reason me to read the standard in depth. I would not be able to continue this debate otherwise.
The standard states quite clearly in section 1.10 clause 21: The execution of a program contains a data race if it contains two conflicting actions in different threads, at least one of which is not atomic, and neither happens before the other. Any such data race results in undefined behavior.
However, the term undefined behavior is also defined in the standard, section 1.3.24: behavior for which this International Standard imposes no requirements... Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment...
Taking Sebasian's answer regarding std::terminate into account, and working under the assumption that these threads will not throw an exception thereby causing premature termination; while the standard doesn't define the result - it is fairly evident what it may be because of the simplicity of the algorithm. In other words, while the 100% accurate answer would be that the result is undefined - I still maintain that the range of possible outcomes is well defined and is 10-30 due to the characteristic of the environment.
BTW - I really wanted to make this a comment instead of another answer, however it was too long
I wrote the following code:
int i = 0;
switch(i++)
{
case 0:
cout << 0;
case 1:
cout << 1;
}
cout << "\n" << i;
The output of the code was like this:
01
1
Can anyone please explain the first line of output? Why are 0 and 1 both being printed?
First, the expression i++ (post-increment operator) evaluates to 0 (even though it sets the value of i to 1). So inside the switch, the case 0: branch is selected.
Then, because there is no break after your case 0:, the program continues with executing the code in the case 1: label.
Summing it up, you have: 0 from the first switch branch, 1 from the second branch, and another 1 because that's the final value of i.
Because you need to add a break after each case, which prevents execution of the following statements. E.g.
switch(i++)
{
case 0:
cout<<0;
break;
case 1:
cout<<1;
break;
}
Admittedly, the second break is superfluous but I put it there just for the sake of consistency
you need to put "break;" at the end of each case.
switch is a strange construct. It comes from C, and Java and C# adopted it too, so it is not considered totally "non-OO".
switch on state which changes is a valid OO concept, but often is used for switching based on type.
In particular the compiler usually creates a "jump" table which means it is O(1) what block of code gets called, unlike a nested "if" statement. You may have multiple values (not including default) jump to the same point, thus code blocks "run into" each other unless you explicitly insert a "break" statement.
This is how it was done in C and has been retained for C++.
With regards to the value in the switch, it must be a numeric value but does not have to be a constant. In your case i++ evaluates to 0 but increments i to 1. This is well-defined behaviour and there is no issues with sequence points here.