What is the advantage of commas in a conditional statement?

后端 未结 7 1720
醉酒成梦
醉酒成梦 2021-02-03 17:25

We can write an if statement as

if (a == 5, b == 6, ... , thisMustBeTrue)

and only the last condition should be satisfiable to ent

相关标签:
7条回答
  • 2021-02-03 17:34

    None whatsoever. The comparisons on a in that code are completely redundant.

    0 讨论(0)
  • 2021-02-03 17:36

    Changing your example slightly, suppose it was this

    if ( a = f(5), b = f(6), ... , thisMustBeTrue(a, b) )
    

    (note the = instead of ==). In this case the commas guarantee a left to right order of evaluation. In constrast, with this

    if ( thisMustBeTrue(f(5), f(6)) )
    

    you don't know if f(5) is called before or after f(6).

    More formally, commas allow you to write a sequence of expressions (a,b,c) in the same way you can use ; to write a sequence of statements a; b; c;. And just as a ; creates a sequence point (end of full expression) so too does a comma. Only sequence points govern the order of evaluation, see this post.

    But of course, in this case, you'd actually write this

    a = f(5);
    b = f(6);    
    if ( thisMustBeTrue(a, b) )
    

    So when is a comma separated sequence of expressions preferrable to a ; separated sequence of statements? Almost never I would say. Perhaps in a macro when you want the right-hand side replacement to be a single expression.

    0 讨论(0)
  • 2021-02-03 17:36

    In short: Although it is legal to do so, it usually doesn't make sense to use the comma operator in the condition part of an if or while statement (EDIT: Although the latter might sometimes be helpful as user5534870 explains in his answer).

    A more elaborate explanation: Aside from its syntactic function (e.g. separating elements in initializer lists, variable declarations or function calls/declarations), in C and C++, the , can also be a normal operator just like e.g. +, and so it can be used everywhere, where an expression is allowed (in C++ you can even overload it).
    The difference to most other operators is that - although both sides get evaluated - it doesn't combine the outputs of the left and right expressions in any way, but just returns the right one.
    It was introduced, because someone (probably Dennis Ritchie) decided for some reason that C required a syntax to write two (or more) unrelated expressions at a position, where you ordinarily only could write a single expression.

    Now, the condition of an if statement is (among others) such a place and consequently, you can also use the , operator there - whether it makes sense to do so or not is an entirely different question! In particular - and different from e.g. function calls or variable declarations - the comma has no special meaning there, so it does, what it always does: It evaluates the expressions to the left and right, but only returns the result of the right one, which is then used by the if statement.

    The only two points I can think of right now, where using the (non-overloaded) ,-operator makes sense are:

    1. If you want to increment multiple iterators in the head of a for loop:

      for ( ... ; ... ; ++i1, ++i2){
          *i2=*i1;
      }
      
    2. If you want to evaluate more than one expression in a C++11 constexpr function.

    To repeat this once more: Using the comma operator in an if or while statement - in the way you showed it in your example - isn't something sensible to do. It is just another example where the language syntaxes of C and C++ allow you to write code, that doesn't behave the way that one - on first glance - would expect it to. There are many more....

    0 讨论(0)
  • 2021-02-03 17:36

    What follows is a bit of a stretch, depending on how devious you might wish to be.

    Consider the situation where a function returns a value by modifying a parameter passed by reference or via a pointer (maybe from a badly designed library, or to ensure that this value is not ignored by not being assigned after returning, whatever).

    void calculateValue(FooType &result) {/*...*/}
    

    Then how do you use conditional statements that depend on result?

    You could declare the variable that will be modified, then check it with an if:

    FooType result;
    calculateValue(result);
    if (result.isBared()) {
        //...
    }
    

    This could be shortened to

    FooType result;
    if (calculateValue(result) , result.isBared()) {
        //...
    }
    

    Which is not really worth while. However, for while loops there could be some small advantages. If calculateValue should/can be called until the result is no longer bar'd, we'd have something like:

    FooType result;
    calculateValue(result);  //[1] Duplicated code, see [2]
    while (result.isBared()) {
        //... possibly many lines
        //separating the two places where result is modified and tested
    
        //How do you prevent someone coming after you and adds a `continue`
        //here which prevents result to be updated in the and of the loop?
    
        calculateValue(result); //[2] Duplicated code, see [1]
    }
    

    and could be condensed to:

    FooType result;
    while (calculateValue(result) , result.isBared()) {
        //all your (possibly numerous) code lines go here
    }
    

    This way the code to update result is in only one place, and is near the line where its conditions are checked.

    maybe unrelated: Another reason why variables could be updated via parameter passing is that the function needs to return the error code in addition to modify/return the calculated value. In this case:

    ErrorType fallibleCalculation(FooType &result) {/*...*/}
    

    then

    FooType result;
    ErrorType error;
    
    while (error = fallibleCalculation(result) , (Success==error && result.isBared())) {
        //...
    }
    

    but as noted in the comments, you can do this without the comma too:

    FooType result;
    ErrorType error;
    
    while (Success == fallibleCalculation(result) && result.isBared()) {
        //...
    }
    
    0 讨论(0)
  • 2021-02-03 17:40

    For an if statement, there is no real point in putting something into a comma expression rather than outside.

    For a while statement, putting a comma expression to the condition executes the first part either when entering the loop, or when looping. That cannot easily be replicated without code duplication.

    So how about a s do...while statement? There we have only to worry about the looping itself, right? It turns out that not even here a comma expression can be safely replace by moving the first part into the loop.

    For one thing, destructors for variables in the loop body will not have already been run then which might make a difference. For another, any continue statement inside the loop will reach the first part of the comma expression only when it indeed is in the condition rather than in the loop body.

    0 讨论(0)
  • 2021-02-03 17:44

    There is no advantage: the comma operator is simply an expression with type of the last expression in its expression list and an if statement evaluates a boolean expression.

    if(<expr>) { ... }
     with type of <expr> boolean
    

    It's a weird operator true, but there's no magic to it - except that it confuses lists of expressions with argument lists in function calls.

    foo(<args>)
     with <args> := [<expr>[, <expr>]*]
    

    Note that in the argument list, comma binds stronger to separating arguments.

    0 讨论(0)
提交回复
热议问题