Strange abortion of for loop

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • hall

    Strange abortion of for loop

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

  • Leor Zolman

    #2
    Re: Strange abortion of for loop

    On Wed, 14 Apr 2004 16:19:19 +0200, hall <Xcrackhead_eX@ yahoo.se> wrote:
    [color=blue]
    >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?)[/color]

    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
    [color=blue]
    >
    >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
    >-----------------[/color]

    --
    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:
    An STL Error Decryptor for C++ by Leor Zolman of BD Software - available to download here

    Comment

    • Bill Seurer

      #3
      Re: Strange abortion of for loop

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

      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().

      Comment

      • Ioannis Vranos

        #4
        Re: Strange abortion of for loop

        "hall" <Xcrackhead_eX@ yahoo.se> wrote in message
        news:c5jh9q$3m2 $1@eol.dd.chalm ers.se...[color=blue]
        > 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)[/color]


        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.
        [color=blue]
        > }
        > 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,[/color]


        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

        Comment

        • hall

          #5
          Re: Strange abortion of for loop

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

          [color=blue]
          >
          > 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.
          >[/color]

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

          Comment

          Working...