replacement of 'if' ?

Discussion in 'C Programming' started by Mark, Jun 19, 2009.

  1. Mark

    Mark Guest

    Hello

    I recently encountered this slightly obfiscating code:

    void foo(int a)
    {
    a > 0 && puts("+");
    }

    seems this is to replace 'if-else' chain as in:

    if (a > 0)
    printf();
    ....

    But I can't precisely understand the underlying mechanics of '&&' operator
    above: 'a > 0' evaluates 1 or 0 depending on the value of 'a', but how does
    && apply to the second operand, which is function ?

    --
    Mark
     
    Mark, Jun 19, 2009
    #1
    1. Advertising

  2. Mark

    Chris Dollin Guest

    Mark wrote:

    > Hello
    >
    > I recently encountered this slightly obfiscating code:
    >
    > void foo(int a)
    > {
    > a > 0 && puts("+");
    > }
    >
    > seems this is to replace 'if-else' chain as in:
    >
    > if (a > 0)
    > printf();
    > ...
    >
    > But I can't precisely understand the underlying mechanics of '&&' operator
    > above: 'a > 0' evaluates 1 or 0 depending on the value of 'a', but how does
    > && apply to the second operand, which is function ?


    It doesn't matter what the right operand of `&&` is; the evaluation
    rule is: evaluate the left operand; yeild 0 if that yeilded 0; otherwise
    evaluate the right operand and yeild whatever that yeilds.

    (The second operand of `&&` above isn't a function, it's a function
    /call/.)

    --
    '"Why is it," I asked Will, after the seventh or eigth time, /Deep Secret/
    "that they see a thing and don't know what it is, and I tell
    them that it's an unidentified flying object, and they go away
    perfectly satisfied?"

    Hewlett-Packard Limited Cain Road, Bracknell, registered no:
    registered office: Berks RG12 1HN 690597 England
     
    Chris Dollin, Jun 19, 2009
    #2
    1. Advertising

  3. Mark

    Mark Guest

    "Chris Dollin" <> wrote in message
    news:h1fe1o$6cs$...
    > It doesn't matter what the right operand of `&&` is; the evaluation
    > rule is: evaluate the left operand; yeild 0 if that yeilded 0; otherwise
    > evaluate the right operand and yeild whatever that yeilds.
    >
    > (The second operand of `&&` above isn't a function, it's a function
    > /call/.)

    Thank you, you've cleared my doubts.

    --
    Mark
     
    Mark, Jun 19, 2009
    #3
  4. Chris Dollin <> writes:
    >> I recently encountered this slightly obfiscating code:
    >>
    >> void foo(int a)
    >> {
    >> a > 0 && puts("+");
    >> }
    >>
    >> seems this is to replace 'if-else' chain as in:
    >>
    >> if (a > 0)
    >> printf();
    >> ...
    >>
    >> But I can't precisely understand the underlying mechanics of '&&' operator
    >> above: 'a > 0' evaluates 1 or 0 depending on the value of 'a', but how does
    >> && apply to the second operand, which is function ?

    >
    > It doesn't matter what the right operand of `&&` is; the evaluation
    > rule is: evaluate the left operand; yeild 0 if that yeilded 0; otherwise
    > evaluate the right operand and yeild whatever that yeilds.


    Close, but not quite.

    Both operands of "&&" have to be scalar. puts() returns an int, so it
    can be used here; a call to a function returning void would be
    invalid.

    The "&&" operator yields 1 if both its operands are non-zero, 0
    otherwise.

    If the left operand is 0, the right operand is not evaluated, which is
    what makes it act like an if statement. But using an if statement
    would have been clearer.

    (This kind of thing is a fairly common idiom in shell scripts.)

    [...]

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Jun 19, 2009
    #4
  5. Mark

    Mark Guest

    "Keith Thompson" <> wrote in message
    news:...
    > Both operands of "&&" have to be scalar. puts() returns an int, so it
    > can be used here; a call to a function returning void would be
    > invalid.
    >
    > The "&&" operator yields 1 if both its operands are non-zero, 0
    > otherwise.


    So I also may write:

    fprintf(...) || exit(EXIT_FAILURE);

    The '||' operator will yield 1 if at least one operand is non-zero, in other
    words if 'fprintf' fails, the 'exit' call is invoked and this would be equal
    to:

    if (fprintf(..) == 0)
    exit();

    --
    Mark
     
    Mark, Jun 19, 2009
    #5
  6. On 19 June, 09:50, pete <> wrote:
    > Mark wrote:
    > > "Keith Thompson" <> wrote in message
    > >news:...


    > >> Both operands of "&&" have to be scalar.  puts() returns an int, so it
    > >> can be used here; a call to a function returning void would be
    > >> invalid.

    >
    > >> The "&&" operator yields 1 if both its operands are non-zero, 0
    > >> otherwise.

    >
    > > So I also may write:

    >
    > > fprintf(...) || exit(EXIT_FAILURE);

    >
    > Yes, you may,
    > but don't forget that it is "slightly obfiscating code".


    but it's a common idiom in Perl! Oh wait...
     
    Nick Keighley, Jun 19, 2009
    #6
  7. Mark

    Chris Dollin Guest

    Keith Thompson wrote:

    > Chris Dollin <> writes:
    >>> I recently encountered this slightly obfiscating code:
    >>>
    >>> void foo(int a)
    >>> {
    >>> a > 0 && puts("+");
    >>> }
    >>>
    >>> seems this is to replace 'if-else' chain as in:
    >>>
    >>> if (a > 0)
    >>> printf();
    >>> ...
    >>>
    >>> But I can't precisely understand the underlying mechanics of '&&' operator
    >>> above: 'a > 0' evaluates 1 or 0 depending on the value of 'a', but how does
    >>> && apply to the second operand, which is function ?

    >>
    >> It doesn't matter what the right operand of `&&` is; the evaluation
    >> rule is: evaluate the left operand; yeild 0 if that yeilded 0; otherwise
    >> evaluate the right operand and yeild whatever that yeilds.

    >
    > Close, but not quite.
    >
    > Both operands of "&&" have to be scalar.


    Yes, but that wasn't the "didn't matter" I meant (since, if an
    operand was not scalar, then there's a constraint violation, and
    All Bets Are Off as to any run-time behaviour); I meant that it
    didn't matter that the right operand was a function [call] rather
    than a variable or a sum or whatever. I should have accounted for
    that.

    I was ... distracted. Yes. That's it. Distracted.

    --
    "You're down as expendable. You don't get a weapon." /Dark Lord of Derkholm/

    Hewlett-Packard Limited registered office: Cain Road, Bracknell,
    registered no: 690597 England Berks RG12 1HN
     
    Chris Dollin, Jun 19, 2009
    #7
  8. "Mark" <> writes:
    > "Keith Thompson" <> wrote in message
    > news:...
    >> Both operands of "&&" have to be scalar. puts() returns an int, so it
    >> can be used here; a call to a function returning void would be
    >> invalid.
    >>
    >> The "&&" operator yields 1 if both its operands are non-zero, 0
    >> otherwise.

    >
    > So I also may write:
    >
    > fprintf(...) || exit(EXIT_FAILURE);


    Well, you may, but you shouldn't expect the compiler to accept it.
    exit() returns void, which means that exit(EXIT_FAILURE) isn't a
    scalar expression, so it can't be an operand of "||".

    (Similarly, "return EXIT_FAILURE" can't be used here either, because
    it's not an expression at all.)

    Furthermore, fprintf() doesn't return an exit/failure result that you
    can use in this context. It returns the number of characters printed
    on success, or a negative value on an error. So you're going to
    terminate the program only if fprintf() prints zero characters, and
    continue if there's an error. I doubt that's what you want.

    If you're really determined to use "||, you could do something like
    this:

    fprintf(...) >= 0 || (exit(EXIT_FAILURE), 0);

    The left operand is true if and only if fprintf() succeeded. The
    right operand uses the exit call as the left operand of a comma
    operator (which is valid); the right operand as a whole yields the int
    value 0, which is then discarded.

    At this point, you should realize that C has the "if" keyword for very
    good reasons.

    > The '||' operator will yield 1 if at least one operand is non-zero, in
    > other words if 'fprintf' fails, the 'exit' call is invoked and this
    > would be equal to:
    >
    > if (fprintf(..) == 0)
    > exit();


    It would be if exit() returned a scalar result.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Jun 19, 2009
    #8
  9. Mark

    Eric Sosman Guest

    Mark wrote:
    >
    > "Keith Thompson" <> wrote in message
    > news:...
    >> Both operands of "&&" have to be scalar. puts() returns an int, so it
    >> can be used here; a call to a function returning void would be
    >> invalid.
    >>
    >> The "&&" operator yields 1 if both its operands are non-zero, 0
    >> otherwise.

    >
    > So I also may write:
    >
    > fprintf(...) || exit(EXIT_FAILURE);


    No, because the type of the sub-expression `exit(...)'
    is `void', and both operands of `||' must be scalars. You
    could repair things by using the comma operator

    fprintf(...) || (exit(EXIT_FAILURE), 0);

    > The '||' operator will yield 1 if at least one operand is non-zero, in
    > other words if 'fprintf' fails, [...]


    If fprintf() fails, it returns a negative number -- and
    since a negative number is non-zero, it means "true." The
    only way fprintf() can return zero is if it generates no
    output characters, that is, if it's `fprintf("")'.

    --
    Eric Sosman
    lid
     
    Eric Sosman, Jun 19, 2009
    #9
  10. On Fri, 19 Jun 2009 01:09:58 -0700, Keith Thompson <>
    wrote:

    > Chris Dollin <> writes:


    > > It doesn't matter what the right operand of `&&` is; the evaluation
    > > rule is: evaluate the left operand; yeild 0 if that yeilded 0; otherwise
    > > evaluate the right operand and yeild whatever that yeilds.

    >
    > Close, but not quite.
    >
    > Both operands of "&&" have to be scalar. puts() returns an int, so it
    > can be used here; a call to a function returning void would be
    > invalid.
    >
    > The "&&" operator yields 1 if both its operands are non-zero, 0
    > otherwise.
    >

    Right. (To be exact, compare not-equal to zero; that includes a
    pointer being non-null.)

    > If the left operand is 0, the right operand is not evaluated, which is
    > what makes it act like an if statement. But using an if statement
    > would have been clearer.
    >

    Clear is in the eye of the beholder. I'm happy with both forms.

    > (This kind of thing is a fairly common idiom in shell scripts.)
    >

    And perl. And in those, it DOES 'return' whatever the right operand
    does, not just 0/1. perl directly yields it; shell leaves it in $? .
    Though in shell the sense is reversed: 0=true other=false.

    Although it is probably most often used in the forms
    something-failed && die
    something-worked || die
    which doesn't return/yield at all in the 'die' case.
     
    David Thompson, Jul 1, 2009
    #10
    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. Youhanna Mounir
    Replies:
    3
    Views:
    567
  2. Praveen Pandey

    replacement for ActiveX in .NET

    Praveen Pandey, Dec 7, 2004, in forum: ASP .Net
    Replies:
    1
    Views:
    3,400
    smith
    Dec 8, 2004
  3. Kermit Lowry
    Replies:
    0
    Views:
    382
    Kermit Lowry
    Sep 25, 2003
  4. mail
    Replies:
    1
    Views:
    538
    Will Stranathan
    Mar 2, 2004
  5. Dave Boland

    VB(ish) replacement

    Dave Boland, Jul 20, 2004, in forum: Perl
    Replies:
    4
    Views:
    593
    Joshua Kugler
    Sep 11, 2004
Loading...

Share This Page