Strange abortion of for loop

Discussion in 'C++' started by hall, Apr 14, 2004.

  1. hall

    hall Guest

    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
    -----------------






    --
    ( - Remove capital X from email to reply - )
     
    hall, Apr 14, 2004
    #1
    1. Advertising

  2. hall

    Leor Zolman Guest

    On Wed, 14 Apr 2004 16:19:19 +0200, hall <> wrote:

    >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
    >-----------------


    --
    Leor Zolman --- BD Software --- www.bdsoft.com
    On-Site Training in C/C++, Java, Perl and Unix
    C++ users: download BD Software's free STL Error Message Decryptor at:
    www.bdsoft.com/tools/stlfilt.html
     
    Leor Zolman, Apr 14, 2004
    #2
    1. Advertising

  3. hall

    Bill Seurer Guest

    hall wrote:

    > //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().
     
    Bill Seurer, Apr 14, 2004
    #3
  4. "hall" <> wrote in message
    news:c5jh9q$3m2$...
    > 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
     
    Ioannis Vranos, Apr 14, 2004
    #4
  5. hall

    hall Guest

    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

    --
    ( - Remove capital X from email to reply - )
     
    hall, Apr 14, 2004
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?Utf-8?B?VGltOjouLg==?=

    Loop the loop...

    =?Utf-8?B?VGltOjouLg==?=, Feb 16, 2005, in forum: ASP .Net
    Replies:
    2
    Views:
    1,393
    Karl Seguin
    Feb 16, 2005
  2. Steven

    while loop in a while loop

    Steven, Mar 24, 2005, in forum: Java
    Replies:
    5
    Views:
    2,257
    Tim Slattery
    Mar 30, 2005
  3. -
    Replies:
    12
    Views:
    701
    Remon van Vliet
    Jun 15, 2005
  4. Byte
    Replies:
    4
    Views:
    420
  5. Isaac Won
    Replies:
    9
    Views:
    397
    Ulrich Eckhardt
    Mar 4, 2013
Loading...

Share This Page