Strange abortion of for loop

H

hall

Hi.

I've come across someting strange. I was trying to make a for-loop
execute repetadly until the function called inside it does not return
true during the entire loop (see program below).

The two lines that confuse me are marked as (1) and (2).

count=0;
bool s(true);
while(s){
s=false;
for (int x=0; x<10; ++x){
//s = s||f(x,count); //(1)
bool tmp =f(x, count); s=s||tmp; //(2)
}
count ++;
}
where f(x,count) is a bool function, returning true for count<3

I thought that they both do the same, ie fun() is executed and bool
variable s = s OR (return from function). However, line (1) will abort
the execution of the for loop already when x=0, whereas line (2) will
let the for loop executs f() 10 times.

Can anyone explain what is going on here and why the two lines don't
behave the same way? Is this the result of some optimization (where the
compiler only looks at changes of variable s and not the side effects of
the function call?)

Full program and outputs for the two different lines are below

regards
/hall



Program code and Outputs
--------------------------

Please scroll down to see the outputs from this program

//-----------------
#include <iostream>
using namespace std;

bool f(int x, int c){
cout << "f("<<x<<","<<c<<")";
return c<3;
}

int main(int argc, char* argv[])
{

bool s(true);
int count(0);

while(s){
s=false;

for (int x=0; x<10; ++x){
//s = s||f(x,count); //(1)
bool tmp =f(x, count); s=s||tmp; //(2)
}

count ++; cout << ", s="<< s<<endl;
}

char a; cin >> a;
return 0;
}
// -------------------


Outputs from program

Case 1) Line (1) is commented out, Output is what I expect:
-----------------
f(0,0)f(1,0)f(2,0)f(3,0)f(4,0)f(5,0)f(6,0)f(7,0)f(8,0)f(9,0), s=1
f(0,1)f(1,1)f(2,1)f(3,1)f(4,1)f(5,1)f(6,1)f(7,1)f(8,1)f(9,1), s=1
f(0,2)f(1,2)f(2,2)f(3,2)f(4,2)f(5,2)f(6,2)f(7,2)f(8,2)f(9,2), s=1
f(0,3)f(1,3)f(2,3)f(3,3)f(4,3)f(5,3)f(6,3)f(7,3)f(8,3)f(9,3), s=0
-----------------

Case 2) Line (2) is commented out, (1) is not. The for loop gets
executed only once when f() returns true.
-----------------
f(0,0), s=1
f(0,1), s=1
f(0,2), s=1
f(0,3)f(1,3)f(2,3)f(3,3)f(4,3)f(5,3)f(6,3)f(7,3)f(8,3)f(9,3), s=0
-----------------
 
L

Leor Zolman

Hi.

I've come across someting strange. I was trying to make a for-loop
execute repetadly until the function called inside it does not return
true during the entire loop (see program below).

The two lines that confuse me are marked as (1) and (2).

count=0;
bool s(true);
while(s){
s=false;
for (int x=0; x<10; ++x){
//s = s||f(x,count); //(1)
bool tmp =f(x, count); s=s||tmp; //(2)
}
count ++;
}
where f(x,count) is a bool function, returning true for count<3

I thought that they both do the same, ie fun() is executed and bool
variable s = s OR (return from function). However, line (1) will abort
the execution of the for loop already when x=0, whereas line (2) will
let the for loop executs f() 10 times.

Can anyone explain what is going on here and why the two lines don't
behave the same way? Is this the result of some optimization (where the
compiler only looks at changes of variable s and not the side effects of
the function call?)

Just from what you've said, it seems pretty clear you're not familiar with
the "short circuit" behavior of the || and && operators. In both cases, if
evaluation of the left-hand operand results in a value that "forces" the
logical result of the entire expression, then the right-hand operand is
guaranteed to NOT be evaluated. Otherwise, the right-hand operand is
evaluated and its value is the result of the binary expression.

In your (1), then, f() will not even be called if s is true (and in that
case, s will remain true). If s were false, then s's new value becomes the
result of the call to f().

In your (2), you're calling f unconditionally in the first part, and the
lack of side-effects in the second part means there's nothing surprising
that can happen /there/ either.
-leor
Full program and outputs for the two different lines are below

regards
/hall



Program code and Outputs
--------------------------

Please scroll down to see the outputs from this program

//-----------------
#include <iostream>
using namespace std;

bool f(int x, int c){
cout << "f("<<x<<","<<c<<")";
return c<3;
}

int main(int argc, char* argv[])
{

bool s(true);
int count(0);

while(s){
s=false;

for (int x=0; x<10; ++x){
//s = s||f(x,count); //(1)
bool tmp =f(x, count); s=s||tmp; //(2)
}

count ++; cout << ", s="<< s<<endl;
}

char a; cin >> a;
return 0;
}
// -------------------


Outputs from program

Case 1) Line (1) is commented out, Output is what I expect:
-----------------
f(0,0)f(1,0)f(2,0)f(3,0)f(4,0)f(5,0)f(6,0)f(7,0)f(8,0)f(9,0), s=1
f(0,1)f(1,1)f(2,1)f(3,1)f(4,1)f(5,1)f(6,1)f(7,1)f(8,1)f(9,1), s=1
f(0,2)f(1,2)f(2,2)f(3,2)f(4,2)f(5,2)f(6,2)f(7,2)f(8,2)f(9,2), s=1
f(0,3)f(1,3)f(2,3)f(3,3)f(4,3)f(5,3)f(6,3)f(7,3)f(8,3)f(9,3), s=0
-----------------

Case 2) Line (2) is commented out, (1) is not. The for loop gets
executed only once when f() returns true.
-----------------
f(0,0), s=1
f(0,1), s=1
f(0,2), s=1
f(0,3)f(1,3)f(2,3)f(3,3)f(4,3)f(5,3)f(6,3)f(7,3)f(8,3)f(9,3), s=0
-----------------
 
B

Bill Seurer

hall said:
//s = s||f(x,count); //(1)
bool tmp =f(x, count); s=s||tmp; //(2)
Can anyone explain what is going on here and why the two lines don't
behave the same way?

The || operator won't evaluate the right side if the left side is true.
After the first time that f() returns true f() won't be called again
for (1). The code for (2) always calls f().
 
I

Ioannis Vranos

hall said:
Hi.

I've come across someting strange. I was trying to make a for-loop
execute repetadly until the function called inside it does not return
true during the entire loop (see program below).

The two lines that confuse me are marked as (1) and (2).

count=0;
bool s(true);
while(s){
s=false;
for (int x=0; x<10; ++x){
//s = s||f(x,count); //(1)

bool tmp =f(x, count); s=s||tmp; //(2)


s=s||tmp means that if s is true it gets reassigned the true value else if
tmp is true s becomes true else if noone is true it is reassigned the false
value since s||tmp evaluates to false.
}
count ++;
}
where f(x,count) is a bool function, returning true for count<3

I thought that they both do the same, ie fun() is executed and bool
variable s = s OR (return from function). However, line (1) will abort
the execution of the for loop already when x=0,


I can't see how line (1) can abort the for loop unless an exception is
thrown or a signal is raised. If you mean that the function call is not
executed 10 times, it happens when after f(x,count) returns true and s gets
that value, at the next evaluations, s evaluates to true so the second
expression is not checked (and thus your functions is not executed at all).
If you want your function to be run 10 times you can make it:

for (int x=0; x<10; ++x){
s = f(x,count) || s;






Ioannis Vranos
 
H

hall

On 2004-04-14 16:40 Leor Zolman spoke thusly

Just from what you've said, it seems pretty clear you're not familiar with
the "short circuit" behavior of the || and && operators. In both cases, if
evaluation of the left-hand operand results in a value that "forces" the
logical result of the entire expression, then the right-hand operand is
guaranteed to NOT be evaluated. Otherwise, the right-hand operand is
evaluated and its value is the result of the binary expression.

Thank you. That was exactly what I needed to hear. Now I understand why
things didn't work the way I thought it would.

And thanks to you others who replied too

regards
hall
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top