What are operators for | & << >>?

Asked

Viewed 2,027 times

18

I was analyzing a code and found some operators I don’t know: |, &, >> and <<. What is the functionality of these operators?

bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;

o1 = bits >> 16 & 0xff;
o2 = bits >> 8 & 0xff;
o3 = bits & 0xff;
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators

2 answers

18


These are called operators bitwise. They do operations directly on us bits of numerical data.

The first two are the or and the and and work in a similar way to || and && but the Boolean calculus is done bit for bit number. Roughly speaking we can say that the or makes a sum of the bits and the and does a multiplication. Truth table of these and other operations.

The following two are operators of shift or displacement of bits. The first one pushes the bits to the right complementing the space on the left with 0. The bits that go more to the right are being discarded. And the second makes in the opposite direction. Each bit left shift multiplies the number by 2 and in right shift it is divided by 2.

As can be seen in the MDN documentation linked above there are still operators of xor (or exclusive) and not which is denial. Remembering that it is always done bit to bit.

All these operations are always done in 32 bit numbers.

A very common use is to accumulate flags as shown below. It is also used in manipulations of scientific data, images (mainly colors) and other forms of media, encryption, compression, checksum for data communication, state machines, in short, just use creativity.

In general it is considered low-level programming and even is often used as a form of optimization, although sometimes there are abuses. x / 2 is equivalent to z >> 1 and x & 1 == 0 is equivalent to x % 2 == 0

It is possible to understand in detail how the calculation is done in the wikipedia article (in English).

var flags = 5;                       // em binário equivale a 0101
var FLAG_A = 1;                      // 0001
var FLAG_B = 2;                      // 0010
var FLAG_C = 4;                      // 0100
var FLAG_D = 8;                      // 1000
var mask = FLAG_A | FLAG_B | FLAG_D; // 0001 | 0010 | 1000 => 1011
if (flags & FLAG_C) {                // 0101 & 0100 => 0100 => true
   // faz alguma coisa
}
if ((flags & FLAG_B) || (flags & FLAG_C)) {
   // faz alguma coisa
}
var mask = FLAG_B | FLAG_C;          // 0010 | 0100 => 0110
if (flags & mask) {                  // 0101 & 0110 => 0100 => true
   // faz alguma coisa
}
var mask = FLAG_C | FLAG_D;          // 0100 | 1000 => 1100
flags |= mask;                       // 0101 | 1100 => 1101
var mask = ~(FLAG_A | FLAG_C);       // ~0101 => 1010
flags &= mask;                       // 1101 & 1010 => 1000
var mask = ~FLAG_A & ~FLAG_C;
flags &= mask;                       // 1101 & 1010 => 1000
var mask = FLAG_B | FLAG_C;
flags = flags ^ mask;                // 1100 ^ 0110 => 1010

I put in the Github for future reference.

Examples taken from MDN documentation.

  • 2

    It might be worth mentioning (since this detail caught me unnoticed before) that no matter the size or type of the number, it is converted into a 32-bit integer before any operation bitwise.

  • @mgibsonbr did not know this but is mentioned by you :)

  • 3

    In the same documentation on MDN linked in your answer this is made explicit, see under "Signed 32-bit integers". At first glance it seems a silly detail, even insignificant, until it comes back to bite you... P

10

Browser other questions tagged

You are not signed in. Login or sign up in order to post.