w3resource

Understanding Bitwise Operators with examples in C

Introduction to Bitwise Operators

Overview

Bitwise operators allow direct manipulation of individual bits within data. They are crucial for systems programming, hardware interfacing, and performance optimizations. In this tutorial, we will explore bitwise operations such as AND, OR, XOR, NOT, bit shifting, and how to use bit masks through examples.

Key Topics:

AND (&) Operator:

Performs a bitwise AND operation. Each bit is compared, and the result is 1 only if both corresponding bits are 1.

When to Use:

  • When you need to check if certain bits are set (i.e., both bits are 1).
  • Used in creating bit masks for clearing specific bits or verifying flags.

Why to Use:

  • Useful for checking or isolating specific bits in bit-level manipulations, such as checking hardware status bits or enabling/disabling specific features.

Example:

The bitwise AND compares two numbers bit by bit, and the result is 1 only if both corresponding bits are 1.

Code:

#include <stdio.h>
int main() {
    int a = 5;  // 5 in binary is 0101
    int b = 3;  // 3 in binary is 0011
    int result = a & b;  // Bitwise AND
    printf("Result of 5 & 3 = %d\n", result);  // Output: 1
    return 0;
}

Output:

Result of 5 & 3 = 1

Explanation:

  • 5 in binary: 0101
  • 3 in binary: 0011
  • 5 & 3: 0001 (Only the last bit is 1 in both numbers).

OR (|) Operator:

Performs a bitwise OR operation. Each bit is compared, and the result is 1 if either of the corresponding bits is 1.

When to Use:

  • To set particular bits to 1 in a number without changing other bits.
  • Useful for setting specific flags or combining multiple conditions.

Why to Use:

  • Handy when you want to enable a specific feature or setting by manipulating individual bits.

Example:

The bitwise OR operation results in 1 when either of the bits in the two numbers is 1.

Code:

#include <stdio.h>
int main() {
    int a = 5;  // 5 in binary is 0101
    int b = 3;  // 3 in binary is 0011
    int result = a | b;  // Bitwise OR
    printf("Result of 5 | 3 = %d\n", result);  // Output: 7
    return 0;
}

Output:

Result of 5 | 3 = 7

Explanation:

  • 5 in binary: 0101
  • 3 in binary: 0011
  • 5 | 3: 0111 (If either bit is 1, the result is 1).

XOR (^) operator

Performs a bitwise XOR operation. Each bit is compared, and the result is 1 only if the corresponding bits differ.

When to Use:

  • To toggle bits between 0 and 1.
  • Can be used to swap two variables without a temporary variable.

Why to Use:

  • Useful for flipping specific bits, performing parity checks, or detecting bitwise changes.

Example:

Bitwise XOR compares two numbers bit by bit, and the result is 1 if the bits differ.

Code:

#include <stdio.h>

int main() {
    int a = 5;  // 5 in binary is 0101
    int b = 3;  // 3 in binary is 0011
    int result = a ^ b;  // Bitwise XOR
    printf("Result of 5 ^ 3 = %d\n", result);  // Output: 6
    return 0;
} 

Output:

Result of 5 ^ 3 = 6 

Explanation:

  • 5 in binary: 0101
  • 3 in binary: 0011
  • 5 ^ 3: 0110 (If the bits are different, the result is 1).

NOT (~) operator

Inverts all the bits in a number. Each 0 becomes 1 and each 1 becomes 0.

When to Use:

  • To reverse all the bits in a number.
  • Often used to apply bit-level negation in bit masks or perform two’s complement operations.

Why to Use:

  • Useful when you want to invert bit values, especially for creating masks or flipping specific bits.

Example:

The bitwise NOT operator inverts all the bits in a number, converting 0s to 1s and vice versa.

Code:

#include <stdio.h>
int main() {
    int a = 5;  // 5 in binary is 0101
    int result = ~a;  // Bitwise NOT

    printf("Result of ~5 = %d\n", result);  // Output: -6
    return 0;
}

Output:

Result of ~5 = -6

Explanation:

  • 5 in binary: 00000000 00000000 00000000 00000101
  • ~5 in binary: 11111111 11111111 11111111 11111010 (Flipping each bit).
  • The result is -6 due to two's complement representation for negative numbers.

Left Shift (<<) operator

Shifts the bits of a number to the left by a specified number of positions, filling the new bits with 0.

When to Use:

  • To multiply a number by powers of 2.
  • Commonly used in embedded systems and low-level programming to pack or align data efficiently.

Why to Use:

  • Improves efficiency when multiplying by 2^n, as it avoids costly multiplication operations.

Example:

Left shifting shifts bits to the left by a specified number of positions, effectively multiplying the number by 2 for each shift.

Code:

#include <stdio.h>
int main() {
    int a = 5;  // 5 in binary is 0101
    int result = a << 1;  // Left shift by 1

    printf("Result of 5 << 1 = %d\n", result);  // Output: 10
    return 0;
}

Output:

Result of 5 << 1 = 10

Explanation:

  • Shifting 5 (binary 0101) left by one position gives 1010, which is 10 in decimal.

Right Shift (>>) operator

Shifts the bits of a number to the right by a specified number of positions. The new leftmost bits depend on the number's sign (0 for unsigned, sign-extended for signed).

When to Use:

  • To divide a number by powers of 2.
  • Commonly used to extract parts of packed data.
  • Why to Use:
    • Provides a fast way to divide numbers by powers of 2, especially in performance-sensitive code.

    Example:

    Right shifting shifts bits to the right by a specified number of positions, effectively dividing the number by 2 for each shift.

    Code:

    #include <stdio.h>
    
    int main() {
        int a = 5;  // 5 in binary is 0101
        int result = a >> 1;  // Right shift by 1
        printf("Result of 5 >> 1 = %d\n", result);  // Output: 2
        return 0;
    }
    

    Output:

    Result of 5 >> 1 = 2
    

    Explanation:

    • Shifting 5 (binary 0101) right by one position gives 0010, which is 2 in decimal.

    Using Bit Masks

    A bit mask is a pattern of bits used to select or manipulate specific bits in a number.

    When to Use:

    • To isolate, set, or clear specific bits in a number.
    • Frequently used in hardware programming, protocol design, and situations where specific flags or features are controlled by individual bits.

    Why to Use:

    • Bit masks provide a precise way to manipulate data at the bit level, allowing you to work with specific bits without affecting others. They are essential in managing flags, permissions, or configuration settings in low-level programming.

    Example:

    Bit masks are used to isolate or manipulate specific bits within a number, often using the AND operation to clear or retain specific bits.

    Code:

    #include <stdio.h>
    int main() {
        int num = 0b1101;  // Binary representation: 1101
        int mask = 0b0100;  // Mask: 0100
        int result = num & mask;  // Applying the mask using AND
        printf("Result of masking 1101 with 0100 = %d\n", result);  // Output: 4
        return 0;
    }
    

    Output:

    Result of masking 1101 with 0100 = 4
    

    Explanation:

    • The binary number 1101 is masked with 0100, and the result is 0100 which is 4 in decimal.
    

    Become a Patron!

    Follow us on Facebook and Twitter for latest update.

    It will be nice if you may share this link in any developer community or anywhere else, from where other developers may find this content. Thanks.

    https://w3resource.com/c-programming/c-bitwise-operators.php