Thread: What's going on in this binary operation?

  1. #1
    Registered User
    Join Date
    Jan 2013
    Posts
    40

    What's going on in this binary operation?

    w1 &= 0xFFFFFFFE;


    The book says it "For
    example, to set the low-order bit of an int called w1 to 0, you can AND w1 with an int
    consisting of all 1s except for a single 0 in the rightmost bit" and then referred to the above operation."

    I don't understand what it's saying. Can someone explain?

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    It's all about setting and clearing bits.

    To set a bit, you 'or' it with 1
    To clear a bit, you 'and' it with 0
    To leave a bit unchanged when using 'or', use 0
    To leave a bit unchanged when using 'and', use 1

    > w1 &= 0xFFFFFFFE;
    So in binary, we have
    w1 &= 1111 1111 1111 1111 1111 1111 1111 1110;

    Being an 'and' operation, it's leaving all the bits unchanged, except for the least significant bit, which will become zero.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    If you convert the hexadecimal number to binary it should make more sense.
    1111 1111 1111 1111 1111 1111 1111 1110
    Now AND that with another binary number.

  4. #4
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    I tend to write that sort of thing as:
    Code:
    w1 &= ~1;
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  5. #5
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    This is going to annoy a few people (because some people just plain and simple hate this notation), but my favourite way is ~(1<<n) -> Probably because I first learnt C on the AVR microcontroller, and that is the method for writing to registers.

    This clears the bit SPI2X in the register SPSR.
    Code:
    SPSR &= ~(1 << SPI2X); /* No doubled clock frequency */
    Or you can see how a full register can be set up
    Code:
        /* initialize SPI with lowest frequency; max. 400kHz during identification mode of card */
        SPCR = (0 << SPIE) | /* SPI Interrupt Enable */
               (1 << SPE)  | /* SPI Enable */
               (0 << DORD) | /* Data Order: MSB first */
               (1 << MSTR) | /* Master mode */
               (0 << CPOL) | /* Clock Polarity: SCK low when idle */
               (0 << CPHA) | /* Clock Phase: sample on rising SCK edge */
               (1 << SPR1) | /* Clock Frequency: f_OSC / 128 */
               (1 << SPR0);
    Fact - Beethoven wrote his first symphony in C

  6. #6
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    I should also add that if you look through the background files for the device, you will see these bits defined - For the ATmega128 in the example above, the bits were defined as...
    Code:
    /* SPI Status Register - SPSR */
    #define    SPIF         7
    #define    WCOL         6
    #define    SPI2X        0
    
    
    /* SPI Control Register - SPCR */
    #define    SPIE         7
    #define    SPE          6
    #define    DORD         5
    #define    MSTR         4
    #define    CPOL         3
    #define    CPHA         2
    #define    SPR1         1
    #define    SPR0         0
    Fact - Beethoven wrote his first symphony in C

  7. #7
    Registered User
    Join Date
    Jan 2013
    Posts
    40
    Quote Originally Posted by Salem View Post
    It's all about setting and clearing bits.

    To set a bit, you 'or' it with 1
    To clear a bit, you 'and' it with 0
    To leave a bit unchanged when using 'or', use 0
    To leave a bit unchanged when using 'and', use 1

    > w1 &= 0xFFFFFFFE;
    So in binary, we have
    w1 &= 1111 1111 1111 1111 1111 1111 1111 1110;

    Being an 'and' operation, it's leaving all the bits unchanged, except for the least significant bit, which will become zero.
    Thanks. What does the "0x" stand for in "0xFFFFFFFE" again?
    Is it just some notation for hexidecimal?

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Yes.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    Jan 2013
    Posts
    40
    Quote Originally Posted by laserlight View Post
    Yes.
    Okay thanks.
    and if an int is defined as w1=0525u, what does the 0 in the front and u in the end mean?

    u, I think means unsigned, but I haven't seen what the 0 means.

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Octal.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    Registered User
    Join Date
    Jan 2009
    Posts
    1,485
    Quote Originally Posted by Click_here View Post
    For the ATmega128 in the example above, the bits were defined as...
    Makes you wonder why it was not defined as: (1<<7), (1<<6), (1<<5) etc. to begin with.

  12. #12
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    Quote Originally Posted by Subsonics View Post
    Makes you wonder why it was not defined as: (1<<7), (1<<6), (1<<5) etc. to begin with.
    It's so that you can see the 0 or 1 and change it easily, whilst also seeing what bit in the register is being written to - See the example writing to SPCR and note that they are not all (1<<n).

    I find that this is the best way, because I can easily see what is being set and cleared and refer directly to the data sheet. If they were already defined as (1<<n) and you wanted to clear the bit, you would have to omit it or come up with another name for an off definition.

    But as I said earlier, most people hate this notation - I like it because it is a ANSI standard way of dealing with each bit (unlike microchip's use of anonomous bit fields within a union) and it is easy to see what is being set/cleared (unlike CCS where a description of what you want done is defined and you don't actually know what is being set cleared - This makes referring to the data sheet annoying).
    Fact - Beethoven wrote his first symphony in C

  13. #13
    Registered User
    Join Date
    Jan 2009
    Posts
    1,485
    Quote Originally Posted by Click_here View Post


    It's so that you can see the 0 or 1 and change it easily, whilst also seeing what bit in the register is being written to - See the example writing to SPCR and note that they are not all (1<<n).

    But as I said earlier, most people hate this notation - I like it because it is a ANSI standard way of dealing with each bit (unlike microchip's use of anonomous bit fields within a union) and it is easy to see what is being set/cleared (unlike CCS where a description of what you want done is defined and you don't actually know what is being set cleared - This makes referring to the data sheet annoying).
    Yeah I guess it gives you a bit more information, but (0<<n) is the same as omitting the flag to begin with and most api's that I have seen use a mask that is already set to the destined bit, that's all.

    It's not that I hate the notation just curious why they didn't choose to hide the details behind the interface, you could still clear the bit from the mask etc.

  14. #14
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    but (0<<n) is the same as omitting the flag to begin with
    I'd rather see it there, because the 0 doesn't always mean something is turned off and can be ignored - It could be a choice between two modes. And I like to see it commented on line by line, so that there are no surprises.

    just curious why they didn't choose to hide the details behind the interface
    That they made "_BV(n)" for (1<<n) - And I'm sure someone would have made a clearbit(n) and setbit(n) macro and released it on avrfreaks.

    But this goes back to what you like working with -> For me it's easier to change a 0 to 1 and comment then clearbit to setbit and comment

    Open Question
    What is your favourite notation for setting up registers?
    Fact - Beethoven wrote his first symphony in C

  15. #15
    Registered User
    Join Date
    Jan 2009
    Posts
    1,485
    Quote Originally Posted by Click_here View Post
    I'd rather see it there, because the 0 doesn't always mean something is turned off and can be ignored - It could be a choice between two modes. And I like to see it commented on line by line, so that there are no surprises.
    Well, (0<<n) is always 0 regardless of the value of n.

    Quote Originally Posted by Click_here View Post
    That they made "_BV(n)" for (1<<n) - And I'm sure someone would have made a clearbit(n) and setbit(n) macro and released it on avrfreaks.

    But this goes back to what you like working with -> For me it's easier to change a 0 to 1 and comment then clearbit to setbit and comment

    Open Question
    What is your favourite notation for setting up registers?
    I was referring to the constants as "interface", not some utility function to set the bits. Much like say POSIX open() takes a combination of or:ed flags to set the mode without revealing the details of the specific bit position, meaning the constants can be used directly with out the shift operation.

    Regarding your question, I don't have a "favorite" notation, I just got curious about the choice made in this api, because there is very often pros and cons to what ever choice is made. Reflecting over a particular choice can make you better when it comes to defining interfaces yourself.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. I/O operation on binary file
    By barramundi9 in forum C Programming
    Replies: 2
    Last Post: 05-27-2012, 06:17 AM
  2. Please help me in Binary XOR operation using C++?
    By maxstoto in forum C++ Programming
    Replies: 2
    Last Post: 03-23-2011, 02:24 PM
  3. Mathematical Operation
    By madahmad1 in forum C Programming
    Replies: 3
    Last Post: 08-18-2008, 10:46 AM
  4. Replies: 2
    Last Post: 05-09-2008, 07:27 AM
  5. new operation
    By NewGuy100 in forum C Programming
    Replies: 3
    Last Post: 07-28-2005, 10:45 AM