We learned in the previous lesson that, when you declare a variable, the
compiler reserves an amount of space in memory for that variable.
Indeed, as we learned when studying bytes and words, a declared variable
occupies space that resembles a group of small boxes.
Bit manipulation or a bit related operation allows you to control how
values are stored in bits. This is not an operation you will need to
perform very often, especially not in the early stages of your Object
Pascal journey. Nevertheless, bit operations (and related operators) are
present on all GUI or application programming environments, so much
that you should be aware of what they do or what they offer. At this
time, you should (must) be aware of what a bit, byte, and a word are, as
we saw in the previous lesson.
|
Bits Operators: The Bitwise not Operator
|
|
One of the operations you can perform on a bit consists of reversing its
value. That is, if a bit holds a value of 1, you may want to change it
to 0 and vice-versa. This operation can be taken care of by the bitwise
not operator.
Bitwise not is a unary operator that must be placed on the left side of its operand as in
not Value
To perform this operation, the compiler considers each bit that is
part of the operand and inverts the value of each bit from 1 to 0 or
from 0 to 1 depending on the value the bit is holding. This operation
can be resumed in the following table:
|
Consider a number with a byte value such as 248. In Appendix C, we
define how to convert numbers from one system to another (this could be a
good time to review or study Appendix C). Based on this, the binary
value of decimal 248 is 1111 1000 (and its hexadecimal value is 0xF8).
If you apply the bitwise not operator on it to reverse the values of its
bits, you would get the following result:
|
Value |
1 |
1 |
1 |
1 |
1 |
0 |
0 |
0 |
~Value |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
1 |
|
|
|
Comparing Bits: The Bitwise and Operator
|
|
Bitwise and is a binary operator that uses the following syntax
Operand1 and Operand2
This operator considers two values and compares the bit of each with
the corresponding bit of the other value. If both corresponding bits
are 1, the comparison produces 1. Otherwise, that is, if either bit is
0, the comparison produces 0. This comparison is resumed as follows:
|
Bit1 |
Bit2 |
Bit1 and Bit2 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
1 |
0 |
1 |
1 |
1 |
|
Imagine you have two byte values represented as 187 and 242. Based on
Appendix C, the binary value of decimal 187 is 1011 1011 (and its
hexadecimal value is 0xBB). The binary value of decimal 242 is 1111 0010
(and its hexadecimal value is 0xF2). Let’s compare these two values bit
by bit, using the bitwise AND operator:
|
|
Binary |
Decimal |
N1 |
1 |
0 |
1 |
1 |
1 |
0 |
1 |
1 |
187 |
N2 |
1 |
1 |
1 |
1 |
0 |
0 |
1 |
0 |
242 |
N1 and N2 |
1 |
0 |
1 |
1 |
0 |
0 |
1 |
0 |
178 |
|
Most of the times, you will want the compiler to perform this operation
and use the result in your program. This means that you can get the
result of this operation and possibly display it on the console. The
above operation can be performed by the following program:
|
program Project1;
{$APPTYPE CONSOLE}
const N1 = 187;
const N2 = 242;
begin
Writeln(N1, ' and ', N2, ' = ', (N1 and N2));
Write('Press any key to continue...');
Readln;
end.
This would produce:
187 and 242 = 178
Press any key to continue...
Comparing Bits: The Bitwise or Operator
|
|
You can perform another type of comparison on bits using the bitwise or operator. Its syntax is:
Value1 or Value2
Once again, the compiler compares the corresponding bits of each
operand. If at least one of the equivalent bits is 1, the comparison
produces 1. The comparison produces 0 only if both bits are 0. This
operation is resumed as follows:
|
Bit1 |
Bit2 |
Bit1 or Bit2 |
0 |
0 |
0 |
1 |
0 |
1 |
0 |
1 |
1 |
1 |
1 |
1 |
|
Once again, let’s consider decimals 187 and 242. Their bitwise OR comparison would render the following result:
|
|
Binary |
Decimal |
N1 |
1 |
0 |
1 |
1 |
1 |
0 |
1 |
1 |
187 |
N2 |
1 |
1 |
1 |
1 |
0 |
0 |
1 |
0 |
242 |
N1 or N2 |
1 |
1 |
1 |
1 |
1 |
0 |
1 |
1 |
251 |
|
You can also let the compiler perform the operation and produce a result. Here is an example:
|
program Project1;
{$APPTYPE CONSOLE}
const N1 = 187;
const N2 = 242;
begin
Writeln(N1, ' or ', N2, ' = ', (N1 or N2));
Write('Press any key to continue...');
Readln;
end.
This would produce:
187 or 242 = 251
Press any key to continue...
Comparing Bits: The Bitwise-Exclusive xor Operator
|
|
Like the previous two operators, the bitwise-exclusive xor operator performs a bit comparison of two values. It syntax is:
Value1 xor Value2
The compiler compares the bit of one value to the corresponding bit
of the other value. If one of the bits is 0 and the other is 1, the
comparison produces 1. In the other two cases, that is, if both bits
have the same value, the comparison produces 0. This operation is
resumed as
follows:
|
Bit1 |
Bit2 |
Bit1 xor Bit2 |
0 |
0 |
0 |
1 |
0 |
1 |
0 |
1 |
1 |
1 |
1 |
0 |
|
We will again consider decimals 187 and 242. Their bitwise-exclusive xor comparison would render the following result:
|
|
Binary |
Decimal |
N1 |
1 |
0 |
1 |
1 |
1 |
0 |
1 |
1 |
187 |
N2 |
1 |
1 |
1 |
1 |
0 |
0 |
1 |
0 |
242 |
N1 xor N2 |
0 |
1 |
0 |
0 |
1 |
0 |
0 |
1 |
73 |
|
If the compiler performs this operation, it can produce a result as in the following example:
|
program Project1;
{$APPTYPE CONSOLE}
const N1 = 187;
const N2 = 242;
begin
Writeln(N1, ' xor ', N2, ' = ', (N1 xor N2));
Write('Press any key to continue...');
Readln;
end.
This would produce:
187 xor 242 = 73
Press any key to continue...
Bit Shift Operators: The Left Shift shl
|
|
In the previous lesson, we learned that bits are aligned in some
consecutive manner to store data as needed. One operation you can
perform on such bits consists of moving bits in a direction of your
choice.
Object Pascal provides the left shift operator represented with shl and its syntax is:
Value shl ConstantInteger
The left shift operator, shl, is a binary operator whose
right operand must be a constant integer. When performing the operation,
the compiler would “push” Value’s bits to the left by the number of
ConstantInteger. The number of ConstantInteger bits
on the left side of Value would disappear. The bits on the left side of
Value would replace them. After moving to the left, the space left by
the most right bits would be filled with 0 bits.
Imagine you have a variable named Value and whose value is 42. The
binary value of 42 is 0010 1010. Imagine you want to shift Value to the
left by 2 bits. You would proceed as follows:
|
|
|
0 |
0 |
1 |
0 |
1 |
0 |
1 |
0 |
42 Shifted to the left by 2 bits << 2 |
0 |
0 |
1 |
0 |
1 |
0 |
1 |
0 |
0 |
0 |
|
The resulting binary number is 1010 1000 and its decimal value is 168. This can also be illustrated in the following program:
|
program Project1;
{$APPTYPE CONSOLE}
const Value = 42;
begin
Writeln(Value, ' Shifted Left by 2 = ', Value shl 2);
Write('Press any key to continue...');
Readln;
end.
This would produce:
42 Shifted Left by 2 = 168
Press any key to continue...
Bit Shift Operators: The Right Shift shr
|
|
As opposed to the left operator, the right shift moves bits to the right
by a natural number. Everything is done as for the left shift except
that the concept is applied to the opposite direction.
Therefore, if you shift 42 to the right, the binary result would be 0000 1010, which is equivalent to 10:
|
program Project1;
{$APPTYPE CONSOLE}
const Value = 42;
begin
Writeln(Value, ' Shifted Right by 2 = ', Value shr 2);
Write('Press any key to continue...');
Readln;
end.
This would produce:
42 Shifted Right by 2 = 10
Press any key to continue...
No comments:
Post a Comment