Bitwise Operators in Rust

Bitwise operators in Rust allow manipulation of individual bits in binary representations of data. They are useful for low-level operations like setting or clearing specific bits, creating bitmasks, and optimizing algorithms. Rust provides bitwise AND, OR, XOR, left shift, and right shift operators for efficient bit-level manipulation.

Webdock – Fast Cloud VPS Linux Hosting

Lets’s see some example code and output:

fn main() {
    let value = 0; // You set the value to either 0 or 1.

    // Calculate the exit status using the provided formula:
    let exit_status = (value << 1) | 1;

    // Now, we'll print the value and the resulting exit status.
    println!("Value: {}", value);
    println!("Exit Status: {}", exit_status);

    // Finally, we'll simulate an exit with the calculated exit status.
    std::process::exit(exit_status);
}
Standard Output
Value: 0
Exit Status: 1
fn main() {
    let value = 1; // You set the value to either 0 or 1.

    // Calculate the exit status using the provided formula:
    let exit_status = (value << 1) | 1;

    // Now, we'll print the value and the resulting exit status.
    println!("Value: {}", value);
    println!("Exit Status: {}", exit_status);

    // Finally, we'll simulate an exit with the calculated exit status.
    std::process::exit(exit_status);
}
Standard Output
Value: 1
Exit Status: 3

The Rust code above defines a main function that simulates an exit status calculation and then exits the program using that exit status. Here’s the breakdown:

  1. let value = 0; sets the value to either 0 or 1. You can change this value to 1 if you want to see how it affects the exit status.
  2. let exit_status = (value << 1) | 1; calculates the exit status using a formula:
  • (value << 1) shifts the bits of value one position to the left, which is equivalent to multiplying it by 2.
  • 1 is a binary representation for the number 1.
  • | performs a bitwise OR operation between the left-shifted value and 1, which combines the two binary values.
  1. println!("Value: {}", value); prints the original value (0 or 1) to the console.
  2. println!("Exit Status: {}", exit_status); prints the calculated exit status to the console.
  3. std::process::exit(exit_status); simulates an exit from the program with the calculated exit status. The program will terminate, and the exit status will be returned to the calling process, typically indicating the success or failure of the program. If value is 0, the exit status will be 1, and if value is 1, the exit status will be 3 (due to the left shift).

Use case for bitwise operators in Rust

Suppose we already had another process using 0 for a success exit code, instead we’ve used 33

Why / how does this work?

TL,DR;

In hexadecimal notation, 0x20 represents 32 in decimal, and 1 is 1 in decimal. When you perform a bitwise OR operation (|) between 0x20 and 1, you get 0x21, which is 33 in decimal.

Full explanation:

Let’s break down the binary calculation for 0x20 | 1, which results in 0x21 (or 33 in decimal):

  • 0x20 in binary is 00100000.
  • 1 in binary is 00000001.

Now, let’s perform the bitwise OR operation between these two binary values:

  00100000
| 00000001
-----------
  00100001

The result of the bitwise OR operation is 00100001, which is 0x21 in hexadecimal and 33 in decimal.


fn main() {
    let val = 5;
    println!("{:}",is_even(val));
}

fn is_even(val: u32) -> bool {
    val & 1 == 0
}

Another example, this function will work on any value of any size, because it only ever looks at the least significant bit, so it’s another way of doing modulo 2 == 0.

5 -> 0 1 0 1
1 -> 0 0 0 1
&  _________
1 -> 0 0 0 1 even == False

___

6 -> 0 1 1 0
1 -> 0 0 0 1
&  _________
0 -> 0 0 0 0 even == True

The function effectively checks whether the input number val is even by examining the LSB using bitwise operations and returns true if it’s even and false if it’s odd.

Conclusion

Bitwise operations in Rust are invaluable for optimizing code and saving memory by allowing direct bit manipulation without the need for temporary variables. They are efficient for tasks like creating compact data structures, flag management, and extracting or modifying specific bits. This reduces memory overhead and improves performance in low-level programming scenarios.

Try the code in Rust Playground

Webdock – Fast Cloud VPS Linux Hosting

Previous article

Buffers in Rust