Change a bit of an integer

46,608

Solution 1

You can set the fourth bit of a number by OR-ing it with a value that is zero everywhere except in the fourth bit. This could be done as

x |= (1u << 3);

Similarly, you can clear the fourth bit by AND-ing it with a value that is one everywhere except in the fourth bit. For example:

x &= ~(1u << 3);

Finally, you can toggle the fourth bit by XOR-ing it with a value that is zero everywhere except in the fourth bit:

x ^= (1u << 3);

To see why this works, we need to look at two things:

  1. What is the behavior of the << operator in this context?
  2. What is the behavior of the AND, OR, and XOR operators here?

In all three of the above code snippets, we used the << operator to generate a value. The << operator is the bitwise shift-left operator, which takes a value and then shifts all of its bits some number of steps to the left. In your case, I used

1u << 3

to take the value 1 (which has binary representation 1) and to then shift all its bits over three spots, filling in the missing values with 0. This creates the binary value 1000, which has a bit set in the fourth bit.

Now, why does

x |= (1u << 3);

set the fourth bit of the number? This has to do with how the OR operator works. The |= operator is like += or *= except for bitwise OR - it's equivalent to

x = x | (1u << 3);

So why does OR-ing x with the binary value 1000 set its fourth bit? This has to do with the way that OR is defined:

0 | 0  == 0
0 | 1  == 1
1 | 0  == 1
1 | 1  == 1

More importantly, though, we can rewrite this more compactly as

x | 0  == x
x | 1  == 1

This is an extremely important fact, because it means that OR-ing any bit with zero doesn't change the bit's value, while OR-ing any bit with 1 always sets that bit to one. This means that when we write

x |= (1u << 3);

since (1u << 3) is a value that is zero everywhere except in the fourth bit, the bitwise OR leaves all the bits of x unchanged except for the fourth bit, which is then set to one. More generally, OR-ing a number with a value that is a series of zeros and ones will preserve all the values where the bits are zero and set all of the values where the bits are one.

Now, let's look at

x &= ~(1u << 3);

This uses the bitwise complement operator ~, which takes a number and flips all of its bits. If we assume that integers are two bytes (just for simplicity), this means that the actual encoding of (1u << 3) is

0000000000001000

When we take the complement of this, we get the number

1111111111110111

Now, let's see what happens when we bitwise AND two values together. The AND operator has this interesting truth table:

0 & 0   == 0
0 & 1   == 0
1 & 0   == 0
1 & 1   == 1

Or, more compactly:

x & 0   == 0
x & 1   == x

Notice that this means that if we AND two numbers together, the resulting value will be such that all of the bits AND-ed with zero are set to zero, while all other bits are preserved. This means that if we AND with

~(1u << 3)

we are AND-ing with

1111111111110111

So by our above table, this means "keep all of the bits, except for the fourth bit, as-is, and then change the fourth bit to be zero."

More generally, if you want to clear a set of bits, create a number that is one everywhere you want to keep the bits unchanged and zero where you want to clear the bits.

Finally, let's see why

x ^= (1u << 3)

Flips the fourth bit of the number. This is because the binary XOR operator has this truth table:

0 ^ 0  == 0
0 ^ 1  == 1
1 ^ 0  == 1
1 ^ 1  == 0

Notice that

x ^ 0  == 0
x ^ 1  == ~x

Where ~x is the opposite of x; it's 0 for 1 and 1 for 0. This means that if we XOR x with the value (1u << 3), we're XOR-ing it with

0000000000001000

So this means "keep all the bits but the fourth bit set as is, but flip the fourth bit." More generally, if you want to flip some number of bits, XOR the value with a number that has zero where you want to keep the bits intact and one where you want to flip this bits.

Hope this helps!

Solution 2

You can always use std::bitset which makes modifying bits easy.

Or you can use bit manipulations (assuming you mean 4th bit counting at one. Don't subtract 1 if you mean counting from 0). Note that I use 1U just to guarantee that the whole operation happens on unsigned numbers:

To set: x |= (1U << (4 - 1));

To clear: x &= ~(1U << (4 - 1));

To toggle: x ^= (1U << (4 - 1));

Solution 3

To set the fourth bit, OR with 00001000 (binary).

To clear the fourth bit, AND with 11110111 (binary).

To toggle the fourth bit, XOR with 00001000 (binary).

Examples:

00110010 OR 00001000 = 00111010

00110010 AND 11110111 = 00110010

00110010 XOR 00001000 = 00111010

Solution 4

Simple, since you have, or whatever value you have,

int x = 50;

To set 4th bit (from right) programatically,

int y = x | 0x00000008;

Because, 0x prefixed before a number means it's hexadecimal form. So, 0x0 = 0000 in binary, and 0x8=1000 in binary form. That explains the answer.

Solution 5

Try one of these functions in C language to change n bit

char bitfield;

// start at 0th position

void chang_n_bit(int n, int value)
{
    bitfield = (bitfield | (1 << n)) & (~( (1 << n) ^ (value << n) ));
}

void chang_n_bit(int n, int value)
{
    bitfield = (bitfield | (1 << n)) & ((value << n) | ((~0) ^ (1 << n)));
}

void chang_n_bit(int n, int value)
{
    if(value)
        bitfield |= 1 << n;
    else
        bitfield &= ~0 ^ (1 << n);
}

char print_n_bit(int n)
{
    return (bitfield & (1 << n)) ? 1 : 0;
}
Share:
46,608
pedram
Author by

pedram

Updated on April 05, 2020

Comments

  • pedram
    pedram about 4 years

    We have an integer number

    int x = 50;
    

    in binary, it's

    00110010
    

    How can I change the fourth (4th) bit programatically?

  • Dustin Howett
    Dustin Howett almost 13 years
    1 << 4 is the fifth bit.
  • templatetypedef
    templatetypedef almost 13 years
    @Dustin Howett- Thanks for pointing that out! Fixed.
  • Dustin Howett
    Dustin Howett almost 13 years
    I explained the bit shifts in my answer, which got lost all the way down there. 1<<3 produces a number whose fourth bit is set (0b0001 is shifted to the left three times producing 0b1000,) and the binary operators | and & are 'OR' and 'AND', also described in another answer below.
  • pedram
    pedram almost 13 years
    how does it works ? x |= (1U << (4 - 1)); ?
  • Kerrek SB
    Kerrek SB almost 13 years
    I would generally feel uncomfortable using bitwise operations on signed types. If you want to be absolutely solid, use unsigned types only. (Unsigned integral types have a definite bit representation.)
  • templatetypedef
    templatetypedef almost 13 years
    @pedram- I just updated my answer to go into way more detail. Let me know if there's anything else I can clarify!
  • templatetypedef
    templatetypedef almost 13 years
    @Kerrek SB- Yes, that's a great point. I'll update my answer!
  • timberlake
    timberlake almost 10 years
    This is the best answer that I have read so far... so much clear now!
  • Omar Alshaker
    Omar Alshaker about 6 years
    This answer needs an explaination.
  • Dr. Debasish Jana
    Dr. Debasish Jana about 6 years
    @OmarAlshaker, explained in my ans