Bit-to-bit operations, bit-to-bit operations, or binary logic, usually refer to logical operations done with binary numbers. These operations range from operations AND
, OR
, NOT
, XOR
, NOR
, NAND
, simple bit displacement, among other operations. It should be noted that some of these operations mentioned here are groupings of other operations, such as the NAND
, which is a grouping of a logic AND
with logic NOT
. There are also interesting things to study, such as Boole algebra (or Boolean algebra) and the Theorems by De Morgan.
Operation NOT.
The operation NOT
(NO), also called "negation" or "inversion", is the simplest of operations, as it consists of reversing the state of the bits. Take the binary number as an example 00111100
. After going through an operation NOT
becomes 11000011
. In some programming languages, such as C
, whether to use the operator ~
to reverse bit state. Operation NOT
follows the truth table:
Take as an example the following code in C
:
unsigned char x, y;
x = 44;
printf("x = %d\n", x);
y = ~x;
printf("~x = %d\n", y);
This section gives the following impression:
x = 44
~x = 211
You can check the size a variable occupies in C
through the function call sizeof(type)
. This function returns the size of the variable in bytes, so you need to multiply the result by 8 to get the value in bits.
printf("Tamanho do char é de %d bits e %d byte (s)\n", (sizeof(char) * 8), sizeof(char));
This section gives the following impression:
Tamanho do char é de 8 bits e 1 byte (s)
By the fact of char type in C
be an 8 bit variable when assigning x = 44
what is being done is to assign a variable that contains the value 00101100
. Or rather:
x = 44 é:
128| 64| 32| 16| 8| 4| 2| 1
0| 0| 1 | 0 | 1| 1| 0| 0
Thus, we have 32 + 8 + 4 which is equivalent to the 44 already mentioned. But when the operation is over NOT
, you reverse the state of these bits, getting:
x = 44 é:
0| 0| 1| 0| 1| 1| 0| 0
y = ~x é:
1| 1| 0| 1| 0| 0| 1| 1 Equivalente a 211
One thing that is interesting to note is that the inverse of 44 in an 8-bit variable is 211. An 8-bit variable stores 256 values, being these values from 0 to 255, so it can be said that when making a negation, you get the remaining value at 255 (44 + 211 = 255).
Operation AND.
The operation AND
(E), also called "conjunction", has as symbol the *
or .
and returns 1 when, and only when, all bits are 1 (or true). In the language C
this operation has as symbol the &
between two variables. The operation AND
(OR) is an operation that follows the following truth table:
Let us now take the following code snippet:
y = x & 67;
printf("x & 67 = %d\n", y);
This section gives the following impression:
x & 67 = 0
x
is still equivalent to 44, ie 00101100
binary. When performing an operation AND
with 67 (01000011
in binary) what is actually being done is:
MSB (Most Significant Bit)
x & 67
0 AND 0 => 0
0 AND 1 => 0
1 AND 0 => 0
0 AND 0 => 0
1 AND 0 => 0
1 AND 0 => 0
0 AND 1 => 0
0 AND 1 => 0
LSB (Least Significant Bit)
00000000 binário => 0 decimal
Therefore, an operation AND
amid 44 & 67
returns the number 0, printed on the next line.
Operation OR.
The operation OR
(OR), also called "disjunction", has as symbol the +
. This operation returns 1 when any of the bits is 1 and returns 0 when ALL bits are 0. The operation OR
is an operation that follows the following truth table:
In the C language, the operator is used |
to perform an OR operation between two variables. As in the following code:
y = x | 129;
printf("x | 129 = %d\n", y);
This section gives the following impression:
x | 129 = 173
x
worthwhile 44
, that is to say 00101100
in binary, is in a disjunction operation with 129
(10000001
binary). When performing an operation OR
amid 44
and 129
what is actually being done is:
MSB (Most Significant Bit)
x & 67
0 OR 1 => 1
0 OR 0 => 0
1 OR 0 => 1
0 OR 0 => 0
1 OR 0 => 1
1 OR 0 => 1
0 OR 0 => 0
0 OR 1 => 1
LSB (Least Significant Bit)
10101101 binário => 173 decimal
Therefore, an operation OR
amid 44 & 129
returns the number 173
, printed on the next line.
Operation XOR.
The operation XOR
(Exclusive), also called "exclusive disjunction", is a logical operation between two operands that results in a true logical value if, and only if, exactly one of the operands has true value. It can be synthesized as a difference detector between two logical operands. This operation follows the following truth table:
The XOR operation is an interesting way to change the value of two variables without needing a third, as demonstrated by the excellent answer given by Lucas Nunes in this question.
In the C language, the operator is used ^
to perform an operation XOR
between two variables. As in the following code:
y = x ^167;
printf("x ^167 = %d\n", y);
Which results in the impression:
x ^167 = 139
For 44 (00101100) XOR 167 (10100111)
:
MSB (Most Significant Bit)
x ^ 167
0 XOR 1 => 1
0 XOR 0 => 0
1 XOR 1 => 0
0 XOR 0 => 0
1 XOR 0 => 1
1 XOR 1 => 0
0 XOR 1 => 1
0 XOR 1 => 1
LSB (Least Significant Bit)
10001011 binário => 139 decimal
Therefore, an operation XOR
amid 44 & 167
returns the number 139
, printed on the next line.
Bit offset.
In the language C
operators shall be used >>
or <<
to move bits between variables to the right or left. Bit displacement, as the name already says, is a technique of moving bits to one or more houses. An interesting feature of bit shifting is that it is possible to multiply or divide the value of that variable, but I will not go into detail about this in this answer.
The bit offset works as follows, for example when moving a variable x to the left:
int x = 1; // 0000 0001
int x0 = (x << 0); // 0000 0001 Não deslocado
int x1 = (x << 1); // 0000 0010
int x2 = (x << 2); // 0000 0100
int x3 = (x << 3); // 0000 1000
int x4 = (x << 4); // 0001 0000
int x5 = (x << 5); // 0010 0000
int x6 = (x << 6); // 0100 0000
int x7 = (x << 7); // 1000 0000
Now move to the right:
int x = 128; // 1000 0000
int x0 = (x >> 0); // 1000 0000 Não deslocado
int x1 = (x >> 1); // 0100 0000
int x2 = (x >> 2); // 0010 0000
int x3 = (x >> 3); // 0001 0000
int x4 = (x >> 4); // 0000 1000
int x5 = (x >> 5); // 0000 0100
int x6 = (x >> 6); // 0000 0010
int x7 = (x >> 7); // 0000 0001
I’m not going to delve too deeply into this technique, but I recommend you read Lucas Nunes' excellent answer in this question, where I took the example above. But in the case of the code you provided in your question, what happens is:
y = x << 2;
printf("x <<2 = %d\n", y);
The code snippet above prints:
x <<2 = 176
For:
00101100 em binário é 44 em decimal
00101100 << 2
01011000 //Moveu 1 bit a esquerda
10110000 //Moveu 2 bits a esquerda
10110000 em binário => 176 decimal
y = x >> 2;
printf("x >>2 = %d\n", y);
The code snippet above prints:
x >>2 = 11
For:
00101100 em binário é 44 em decimal
00101100 >> 2
00010110 //Moveu 1 bit a direita
00001011 //Moveu 2 bits a direita
00001011 em binário => 11 decimal
Applications.
Bit operations are often used when programming low level. It is possible to configure microcontroller recorders and perform code optimizations, for example. They are also used in encryption algorithms, because they are logical operations are less expensive to the processor. In digital electronics, they are used at all times.
I don’t think so...
– user24857
@user24857 if it is not duplicate, edit your question and explain what your doubts are, "I can’t understand this" is too generic.
– Renan Gomes
I would like an explanation, I did not understand it. Because the result is ...?
– user24857
I think he’d like a detailed explanation from each operator.
– Ricardo