shortcutting in boolean expressions?

This is a discussion on shortcutting in boolean expressions? within the C++ Programming forums, part of the General Programming Boards category; Eg, if I write something like this Code: if (a() && b()) { //..... } is it possible that b() ...

  1. #1
    Registered User
    Join Date
    Dec 2006
    Location
    Canada
    Posts
    3,183

    shortcutting in boolean expressions?

    Eg, if I write something like this
    Code:
    if (a() && b()) {
         //.....
    }
    is it possible that b() doesn't get evaluated if a() returns false? What does the standard say about this?

    Thank you

  2. #2
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Yes, that's right. If a() returns false, everything to the right of the && won't be executed.

  3. #3
    coder
    Join Date
    Feb 2008
    Posts
    127
    The answer is: b() won't get evaluated if a() returns false.
    I don't know what the standard say about, but this program will tell you:
    Code:
    #include <iostream>
    using namespace std;
    
    bool a ()
    {
    	cout << "a\n";
    	return 0;
    }
    
    bool b ()
    {
    	cout << "b\n";
    	return 1;
    }
    
    int main ()
    {
    	if (a() && b());
    	return 0;
    }

  4. #4
    Registered User
    Join Date
    Dec 2006
    Location
    Canada
    Posts
    3,183
    hmm I see. Thanks for the help. I was just making sure that it is the standard behaviour.

    btw, then, what should I write if I want all of them to be evaluated regardless of the return values? (except making a bunch of temporary variables and recording each return values first of course)

  5. #5
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,274
    The standard says that b() will definitely not be evaluated if a() is false. Code which actually uses this behavior is not uncommon. For instance:

    Code:
    A() && B() && C() && D();
    Will invoke the functions A, B, C, D, in that order, as long as they return true. You can use this to do a multi-part operation in sequence, stopping if anything fails. The alternative using if-statements would be:

    Code:
    if(A())
    {
        if(B())
        {
            if(C())
            {
                D();
            }
        }
    }
    The || operator can be used in the same way but the opposite sense.

  6. #6
    CSharpener vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,484
    Quote Originally Posted by cyberfish View Post
    hmm I see. Thanks for the help. I was just making sure that it is the standard behaviour.

    btw, then, what should I write if I want all of them to be evaluated regardless of the return values? (except making a bunch of temporary variables and recording each return values first of course)
    Using temp vars - is a way, You cannot force compiler evaluate all members of logical expression.

    If your function return only 0 and 1 - you can however switch to binary &
    The first 90% of a project takes 90% of the time,
    the last 10% takes the other 90% of the time.

  7. #7
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,274
    Quote Originally Posted by cyberfish View Post
    btw, then, what should I write if I want all of them to be evaluated regardless of the return values? (except making a bunch of temporary variables and recording each return values first of course)
    Somewhat obscure:

    Code:
    !!a() & !!b()
    Although this does not guarantee the order of evaluation for a() and b(). It does make sure they both get called, and the value of the expression is the same as for the && operator.

  8. #8
    Registered User
    Join Date
    Dec 2006
    Location
    Canada
    Posts
    3,183
    hmm I see... Thanks for the suggestions.

  9. #9
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Note that this is GUARANTEED by the standard, and it allows things like this to work:
    Code:
    if (fgets(buffer, sizeof buffer, stdin) != NULL && buffer[0] != '\n') ... 
    
    // or
    if (x && y / x > 7) ...   // if x == 0, we can't divide by x. 
    
    // or
    if (ptr != NULL && ptr->member == mymember) ...
    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  10. #10
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by cyberfish View Post
    btw, then, what should I write if I want all of them to be evaluated regardless of the return values? (except making a bunch of temporary variables and recording each return values first of course)
    Why would you want to?
    If you only want your if statement to execute if both functions return true, why waste time executing b() if a() already returned false?

  11. #11
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,274
    Quote Originally Posted by cpjust View Post
    Why would you want to?
    If you only want your if statement to execute if both functions return true, why waste time executing b() if a() already returned false?
    Because the function call is part of what is happening. Maybe you want both a() and b() to run but you are also interested if one of them failed. I'd personally just serialize it and check:

    Code:
    a_status = a();
    b_status = b();
    if(a_status && b_status)
        ...

  12. #12
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,893
    Of course, if you have a loop header, this might not work. You could use the comma operator instead.
    Code:
    while(a_status = a(), b_status = b(), a_status && b_status)
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  13. #13
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by CornedBee View Post
    Of course, if you have a loop header, this might not work. You could use the comma operator instead.
    Code:
    while(a_status = a(), b_status = b(), a_status && b_status)
    But couldn't those be evaluated in any order, or is that only for function parameters?

  14. #14
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    22,275
    But couldn't those be evaluated in any order, or is that only for function parameters?
    There is a sequence point at the comma operator, so the order of evaluation is defined here.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  15. #15
    Registered User
    Join Date
    Dec 2006
    Location
    Canada
    Posts
    3,183
    Why would you want to?
    If you only want your if statement to execute if both functions return true, why waste time executing b() if a() already returned false?
    because a() and b() have side effects.

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Novice needs help
    By ghaasemi in forum C++ Programming
    Replies: 9
    Last Post: 05-30-2009, 09:20 AM
  2. Regular expressions [Boost]
    By Desolation in forum C++ Programming
    Replies: 8
    Last Post: 12-30-2006, 10:10 PM
  3. Liitle help with boolean expressions
    By Voyd in forum C++ Programming
    Replies: 2
    Last Post: 05-30-2006, 09:17 PM
  4. Casting boolean as string
    By doofusboy in forum C Programming
    Replies: 11
    Last Post: 11-10-2005, 12:24 PM
  5. Use struct to create a boolean type
    By skyglin in forum C Programming
    Replies: 6
    Last Post: 06-18-2003, 09:21 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21