Bitwise negation
Learn about bitwise negation in detail.
We'll cover the following
Bitwise operations handle each bit of a number individually. We use them often when programming. Let’s consider how they work in detail.
Bitwise negation
First, we will consider the simplest bitwise operation: negation. It is also called bitwise NOT. The tilde symbol (~
) indicates this operation in Bash.
When doing bitwise negation, we swap the value of each bit of an integer. This means that we replace each 1 to 0, and vice versa.
Here is an example of doing bitwise NOT for the number 5:
5 = 101
~5 = 010
The bitwise NOT is a simple operation when we talk about mathematics. However, there are pitfalls when we use it in programming. We should keep two things in mind:
- How many bytes does the number occupy?
- What is the number’s representation in memory?
Let’s suppose that the two-byte variable stores the number 5. Then, it looks like this in memory:
00000000 00000101
When we apply the bitwise NOT for this variable, we get the following result:
11111111 11111010
What do these bits mean? If we store them to the variable of the unsigned integer type, we get the number 65530. If the variable is a signed integer, it equals -6. We can check it by converting the two’s complement representation to decimal.
Various Bash built-ins and operators represent integers in different ways. For example, echo
always outputs numbers as signed integers. The printf
command allows us to choose between a signed and unsigned integer.
There are no types in the Bash language. Bash stores all scalar variables as strings. It converts strings to integers right before inserting them into arithmetic expressions. The number interpretation, signed or unsigned, depends on the context.
Maximum and minimum allowed integers in Bash
Bash allocates 64 bits of memory space for each integer, regardless of its sign. The table below shows maximum and minimum allowed integers in Bash.
Integer | Hexadecimal | Decimal |
---|---|---|
Maximum positive signed | 7FFFFFFFFFFFFFFF | 9223372036854775807 |
Minimum negative signed | 8000000000000000 | -9223372036854775808 |
Maximum unsigned | FFFFFFFFFFFFFFFF | 18446744073709551615 |
The following examples show us how Bash interprets integers in the ((
operator, echo
and printf
built-ins:
$ echo $((16#FFFFFFFFFFFFFFFF))
-1
$ printf "%llu\n" $((16#FFFFFFFFFFFFFFFF))
18446744073709551615
$ if ((18446744073709551615 == 16#FFFFFFFFFFFFFFFF)); then echo "ok"; fi
ok
$ if ((-1 == 16#FFFFFFFFFFFFFFFF)); then echo "ok"; fi
ok
$ if ((18446744073709551615 == -1)); then echo "ok"; fi
ok
Run the commands discussed in this lesson in the terminal below.
Get hands-on with 1200+ tech skills courses.