Search Unity

Bitwise operators question - setting and getting bits in an int

Discussion in 'Scripting' started by darkhog, Jul 7, 2015.

Thread Status:
Not open for further replies.
  1. darkhog

    darkhog

    Joined:
    Dec 4, 2012
    Posts:
    2,218
    This is noob question, I know, but how one sets single bit in an int and read it back? Say, I have 8 bit integer (00000000b) and want to set 4th bit to 1, the read it back. I need it for a little project I'm making, to easily store several boolean values in an int.
     
  2. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    larku likes this.
  3. darkhog

    darkhog

    Joined:
    Dec 4, 2012
    Posts:
    2,218
    Congratulations... on completely missing the point. I know what each bitwise operator does. What I don't know is how to use them to achieve what I want, which is:

    - Setting/unsetting specific bit
    - Checking if specific bit is set or not.
     
    Nyanpas and deus0 like this.
  4. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,537
    the effective results for the operators when applied to a single bit mask:

    OR | - write
    AND & - read
    AND NOT & ~ - clear
    SHIFT << - to create a mask for a specific bit

    Example of a struct that acts as a bitwise boolean array of length 8.

    Code (csharp):
    1.  
    2. public struct BitBool
    3. {
    4.  
    5.     private byte _data;
    6.  
    7.     public bool Value[int index]
    8.     {
    9.         get
    10.         {
    11.             if(index < 0 || index > 7) throw new System.IndexOutOfRangeException();
    12.             return (_data & (1 << index)) > 0;
    13.         }
    14.         set
    15.         {
    16.             if(index < 0 || index > 7) throw new System.IndexOutOfRangeException();
    17.             if(value)
    18.                 _data |= (byte)(1 << index);
    19.             else
    20.                 _data &= ~(byte)(1 << index);
    21.         }
    22.     }
    23.  
    24. }
    25.  
    This is intended for example, a more robust solution should be used if you're attempting to do something like this.

    In the case of .Net/Mono, a more robust solution already exists:
    https://msdn.microsoft.com/en-us/library/system.collections.bitarray(v=vs.110).aspx
     
    Last edited: Jul 7, 2015
    VitasIII and darkhog like this.
  5. booiljoung

    booiljoung

    Joined:
    May 12, 2013
    Posts:
    57
    Here bit test, set, clear example codes.

    Code (CSharp):
    1. example (int bits) {
    2.     // test 4th bit
    3.     if ((bits & (1<<4)) != 0)
    4.         // do action
    5.  
    6.     // set 4th bit.
    7.     bits |= (1<<4);
    8.  
    9.     // clear 4th bit.
    10.     bits &= ~(1<<4);
    11.  
    12. }
    13.  
    14. Define bits
    15.  
    16. class BitFlags {
    17.    public const int example1 = (1<<0);
    18.    public const int example2 = (1<<1);
    19.    public const int example3 = (1<<2);
    20.    public const int optional1 = (1<<3);
    21.    public const int optional2 = (1<<4);
    22.  
    23. }
    24.  
    25. class something
    26. {
    27.    public int optional = 0;
    28.    example() {
    29.        // set bit
    30.        optional |= BitFlags.example1;
    31.  
    32.        // test bit
    33.       if (optional & BitFlags.example2)
    34.            // do something
    35.  
    36.       // clear bit
    37.       optional &= ~BitFlags.optional1;
    38.    }
    39. }
    40.  
    41.  
     
    Last edited: Jul 7, 2015
  6. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,537
    As for why this works.

    A bit mask is creating binary number whose 1's line up with the entries in another piece of bit data you'd like. If you wanted a bitmask for all data it'd be:
    11111111

    If you wanted a bitmask for the first 4 entries (right to left):
    00001111

    If you wanted a bitmask for just the 4th entry (as a 0-index right to left):
    00010000

    In the case of AND, and why it reads a value.

    Say you have the data:
    11010010

    You want to get the value at index 4 (reading right to left). Well you have your bitmask:
    00010000

    Do the operation now:

    11010010
    00010000 &
    ----------
    00010000

    As you go bit by bit. The zero's wash out all values except those that you want. If the slot DIDN'T have info:

    11000010
    00010000 &
    ----------
    00000000

    Note that if your mask is 1 bit in size. It'll return back a non-zero value if there was data in that bit. If there wasn't, it returns back 0. This is why you can use it to "read" data.


    As for writing data. Well lets take the same values:

    11000010
    00010000 |
    ----------
    11010010


    And for clearing data. Well the NOT (~) operator flips all bits in a mask. So if we take our 4th index mask you'll get:

    ~00010000 = 11101111

    Now if we & this you're going to maintain any bits that are written and have 1's in the mask. As for the zero slots, they'll end up zero. So this mask is saying "maintain all bits except the one at the 4th index".

    11010010
    11101111 &
    ----------
    11000010
     
    gop and JoshRunwildEnt like this.
  7. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    There were code examples on the target link... enumeration as specified is the correct numbering for each bit... Dont know what more you wanted... oh I see, you wanted me to ignore you in the future. done.
     
  8. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Unless you are on major platform constraints, I wouldn't suggest doing a ton of bit wise stuff. It can be pretty hellish logic to keep straight, and simply using it to do the job of multiple bools is a bad idea. It can also be very error prone.

    A recent project at work was constrained by some ancient hardware to require using ints in a bit wise fashion. I'd not wish that sort of system on anyone.

    There are cases for bit wise logic. Just make sure you actually need it.
     
    Bankie666 likes this.
  9. darkhog

    darkhog

    Joined:
    Dec 4, 2012
    Posts:
    2,218
    Thank you. That was the answer I was looking for.
     
  10. blizzy

    blizzy

    Joined:
    Apr 27, 2014
    Posts:
    775
    Not sure why you'd need that. You could just write "1 << bit" where "bit" is the bit number. If "bit" is a literal value like "6", a good compiler will always optimize the whole term into a single value, that is, no bit shifting should take place at runtime.
     
  11. SeerSucker69

    SeerSucker69

    Joined:
    Mar 6, 2021
    Posts:
    68
    I am trying to write a function that will set a bit in a INT variable

    The correct answer in c# is to do this: intValue = intValue | (1 << bitPosition);

    This only works in Unity if bitPosition is a constant. If you try this with a variable eg an INT it returns ERROR CS0019 "Operator '<<' can not be applied to operands of type 'int'.

    Anyone know the right way, or a workaround?
     
  12. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,537
    Sure you can. I just did to confirm.

    Code (csharp):
    1.     int Foo(int input, int bits)
    2.     {
    3.         input = input | (1 << bits);
    4.         return input;
    5.     }
    6.  
    7.  
    8. //elsewhere
    9. mask = Foo(mask, someInt);
     
    SeerSucker69 likes this.
  13. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,998
    To be fair, tutorialspoint (that link) is generally terrible and that one was no exception. It's semi-common for people to play around with off-topic Q's -- for example, ones about bit-manipulation in C# that you don't need for Unity. So it feels a little like you gave them a well-known joke site on purpose.
     
  14. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,537
    To be fair, it was 8 years ago.
     
Thread Status:
Not open for further replies.