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.


  • Discourse touched me in a no-no place

    @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