How to invert a boolean



  • Just found this line of C code:


    		blink_mode = (++blink_mode) & 1;

    What's wrong with a simple "blink_mode = !blink_mode"?


  • I once did this



    pause = (pause) ? false : true;


    at 3 AM. I spent 3 minutes the following day staring at it trying to figure out why I did it that way before fixing it.



  • I don't suppose there's any chance that blink_mode could ever be set to a value other than 0 or 1, is there?

    Also, it occurs to me that, depending on the CPU and how smart the compiler is,  x = (++x) & 1 could possibly produce slightly faster code than x = !x, precisely because it doesn't have to treat all non-zero values as true. (In particular, on some architectures C-style boolean negation might require a branch.) Of course, that would be a completely pointless optimization unless that line of code just happened to be part of the critical innermost loop that your CPU-bound program spends 99% of its time in.  And besides, x ^= 1 ought to be even faster anyway.



  • @vyznev said:

    I don't suppose there's any chance that blink_mode could ever be set to a value other than 0 or 1, is there?

    Shouldn't make the least bit of difference to anyone's choice of algorithm though; either method, ! or ++&1, will immediately normalise it into the 0/1 range after the first iteration.




  • @MadnessASAP said:

    I once did this



    pause = (pause) ? false : true;


    at 3 AM. I spent 3 minutes the following day staring at it trying to figure out why I did it that way before fixing it.

    That's just being future-proof.

    Suppose you want pause to be always true.
    You just have to change the code to:

    pause = (pause) ? true : true;

    <font size="1"></sarchasm> </font>



  • On top of that, blink_mode is assigned twice in the same statement, which means the result is actually indeterminate.



  • Unless you're using a system where NULL isn't 0 or 1, and a ! wouldn't normalize it either way...



  • @ZPedro said:

    On top of that, blink_mode is assigned twice in the same statement, which means the result is actually indeterminate.
     

    ROFL, totally overlooked that, but of course it should have been i = (i +1) & 1 if it was to make any sense at all.




  • The most obvious reason, which no one has mentioned yet, is that a negation may include a test-and-jump sequence (which can be very costly), but the algorithmic version can be executed by the CPU without guessing execution paths.

    Old-timer hardcore C programmers tend to avoid if:s at any opportunity.



  • @ZPedro said:

    On top of that, blink_mode is assigned twice in the same statement, which means the result is actually indeterminate.

    Not really, but only because this is a particular special case.  Stating the exact nature of the special case would, however, take more space than I have in this margin.



  • @tgape said:

    @ZPedro said:
    On top of that, blink_mode is assigned twice in the same statement, which means the result is actually indeterminate.

    Not really, but only because this is a particular special case.  Stating the exact nature of the special case would, however, take more space than I have in this margin.

    Perhaps you're balking at the word "indeterminate" when the terminology is "undefined", but this isn't a special case and the result cannot be determined in advance simply by looking at the code and making assumptions: http://c-faq.com/expr/ieqiplusplus.html


  • Perhaps you're balking at the word "indeterminate" when the terminology is "undefined", but this isn't a special case and the result cannot be determined in advance simply by looking at the code and making assumptions: http://c-faq.com/expr/ieqiplusplus.html

    No, no, he's right. In fact, I myself happen to have a practical attack on AES and RSA, the description of which is too big to fit in this margin. :p

    [url=http://www.gap-system.org/~history/Quotations/Fermat.html]Cuius rei demonstrationem mirabilem sane detexi hanc marginis exiguitas non caperet[/url]



  • @Carnildo said:

    blink_mode = (++blink_mode) & 1;

    I particularly like the brackets. Y'know, just in case the pre-increment operator randomly decides to post-increment for a change.



  • Ah, if you needed to toggle and test, you could do this anyways?

    [code]if(blink_mode^=1)[/code]

    Or, with 16X CPU architecture, this?

    [code]F TGL AX ?0. BRZ {.[/code]

    Or, with GameBoy, this?

    [code]XOR $01
    JR Z,[/code]


  • I want to have an update statement like:



    update tblMydate set fieldx=fieldx+1 where code=12



    But then for a boolean value:

    So, if the current boolean value is true, I want to set it to false and vice versa, something like



    update tblMydate set booleanx=not booleanx where code=12



    How can I achieve this?

     

     

    edit: killed erroneous h2 — mod



  • @mamun01 said:



    How can I achieve this?

     

     Simple, create the follwing table:
    CREATE TABLE booleanInv(
    value BOOL PRIMARY_KEY,
    inverted BOOL UNIQUE
    )
    INSERT INTO booleanInv(true,false);
    INSERT INTO booleanInv(false, true);

    now you can use the following query:
    UPDATE tblMydate SET booleanx = (SELECT inverted FROM booleanInv WHERE value = booleanx) WHERE code = 12



  • @ThePants999 said:

    @Carnildo said:

    blink_mode = (++blink_mode) & 1;

    I particularly like the brackets. Y'know, just in case the pre-increment operator randomly decides to post-increment for a change.

    I don't think that's what they're for, I think they're there to prevent the association going wrong.  Without them, the code might be misinterpreted as

    @Carnildo said:
    blink_mode = ++(blink_mode & 1);

    and you could end up accidentally incrementing the value of zero or one!



  • @gms8994 said:

    Unless you're using a system where NULL isn't 0 or 1, and a ! wouldn't normalize it either way...

    Please send some of whatever you were on when you learned C, kthxbye.

     


Log in to reply
 

Looks like your connection to What the Daily WTF? was lost, please wait while we try to reconnect.