0% found this document useful (0 votes)
64 views14 pages

Bit Man Up Lation

The document provides a comprehensive overview of bit manipulation in the C programming language, detailing various bitwise operators and their functionalities. It includes practical examples, problems to solve, and real-world applications in embedded systems. The conclusion emphasizes the importance of mastering bit manipulation for optimizing performance and memory usage.

Uploaded by

Sachin C V Sachi
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
64 views14 pages

Bit Man Up Lation

The document provides a comprehensive overview of bit manipulation in the C programming language, detailing various bitwise operators and their functionalities. It includes practical examples, problems to solve, and real-world applications in embedded systems. The conclusion emphasizes the importance of mastering bit manipulation for optimizing performance and memory usage.

Uploaded by

Sachin C V Sachi
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 14

FEBRUARY 17, 2025

UNDERSTANDING
BIT MANIPULATIONS IN C PROGRAMMING LANGUAGE

VAMSI KRISHNA VAKA


What is Bit Manipulation?
Bit manipulation is the process of directly operating on individual bits of data using bitwise operators. It is
widely used in embedded systems, cryptography, graphics, networking, and data compression due to its
efficiency in performing low-level operations.

Bitwise Operators in C

Bitwise operators allow direct manipulation of bits in variables. They work only on integer data types (int,
char, short, long, etc.).

1. Bitwise AND (&)

Syntax:

result = operand1 & operand2;

Functionality:

• Compares each corresponding bit in two numbers.


• Returns 1 if both bits are 1, otherwise returns 0.

• Used for bit masking (extracting specific bits).

Example:

#include <stdio.h>

int main()

int a = 5, b = 3; // a = 0101, b = 0011


int result = a & b; // 0101 & 0011 = 0001 (1 in decimal)

printf("Bitwise AND: %d\n", result);

return 0;

Output:

Bitwise AND: 1

2. Bitwise OR (|)
Syntax:

result = operand1 | operand2;


Functionality:

• Compares each bit in two numbers.

• Returns 1 if at least one of the bits is 1.


• Used to set specific bits.

Example:

#include <stdio.h>

int main()
{

int a = 5, b = 3; // a = 0101, b = 0011

int result = a | b; // 0101 | 0011 = 0111 (7 in decimal)

printf("Bitwise OR: %d\n", result);

return 0;

Output:

Bitwise OR: 7

3. Bitwise XOR (^)

Syntax:

result = operand1 ^ operand2;

Functionality:

• Returns 1 if bits are different, otherwise returns 0.

• Used to toggle bits (flip 1 to 0 and vice versa).


Example:
#include <stdio.h>

int main()

int a = 5, b = 3; // a = 0101, b = 0011

int result = a ^ b; // 0101 ^ 0011 = 0110 (6 in decimal)

printf("Bitwise XOR: %d\n", result);


return 0;

Output:
Bitwise XOR: 6
4. Bitwise NOT (~)

Syntax:

result = ~operand;
Functionality:

• Inverts all bits (1 becomes 0, 0 becomes 1).

• Used for bit inversion.

• Note: The result is usually negative due to two’s complement representation.

Example:

#include <stdio.h>

int main()

{
int a = 5; // a = 00000101

int result = ~a; // ~00000101 = 11111010 (-6 in decimal)

printf("Bitwise NOT: %d\n", result);

return 0;

Output:

Bitwise NOT: -6

5. Left Shift (<<)

Syntax:

result = operand << n;

Functionality:

• Shifts bits left by n positions.

• Fills vacant bits with 0.


• Equivalent to multiplying by 2^n.

Example:

#include <stdio.h>
int main()

int a = 5; // a = 00000101
int result = a << 2; // 00010100 (20 in decimal)

printf("Left Shift: %d\n", result);

return 0;

}
Output:

Left Shift: 20

6. Right Shift (>>)

Syntax:

result = operand >> n;

Functionality:

• Shifts bits right by n positions.


• Fills leftmost bits with 0 (for unsigned numbers) or sign bit (for signed numbers).

• Equivalent to dividing by 2^n.

Example:

#include <stdio.h>

int main() {

int a = 20; // a = 00010100

int result = a >> 2; // 00000101 (5 in decimal)


printf("Right Shift: %d\n", result);
return 0;

Output:

Right Shift: 5

Problems to Solve
Basic Level

1. Write a C program to check whether a given number is odd or even using bitwise operators.

2. Implement a program to swap two numbers without using a third variable, using bitwise XOR.
3. Write a program to find the nth bit of a number.

Intermediate Level

4. Implement a function to count the number of set bits (1s) in a number.


5. Write a program to toggle a particular bit of a number.

6. Implement a function to check if a number is a power of 2.

Advanced Level

7. Given an integer array, find the unique element (all other elements appear twice).
8. Implement a function to reverse the bits of an integer.

9. Write a function to find the next higher power of 2 for a given number.

Problems:

1. Find the number of set bits in a given number.

#include <stdio.h>

int countSetBits(int num)

{
int count = 0;

while (num)

count += num & 1; // Check the last bit

num >>= 1; // Right shift to process next bit

return count;
}
int main()

int num = 29; // 29 = 11101 (4 set bits)

printf("Number of set bits: %d\n", countSetBits(num));

return 0;

}
Output:

Number of set bits: 4

2. Checking if a Bit is Set


This checks whether a specific bit in a number is 1.
#include <stdio.h>
// Function to check if a bit is set
int isBitSet(int num, int pos)
{
return (num & (1 << pos)) ? 1 : 0;
}
int main()
{
int num = 0b10110110; // 182 in decimal
int pos = 5; // Checking bit at position 5 (0-based index)

if (isBitSet(num, pos))
printf("Bit %d is SET in number %d (Binary: %08b)\n", pos, num, num);
else
printf("Bit %d is NOT set in number %d (Binary: %08b)\n", pos, num, num);
return 0;
}

Explanation:

• 1 << pos shifts 1 to the specified bit position.

• num & (1 << pos) checks if that bit is set (1) or not (0).

• If the result is nonzero, the bit is set.

Example Output:

Bit 5 is SET

2. Setting a Bit

This sets a particular bit to 1 without affecting other bits.

#include <stdio.h>

int setBit(int num, int pos)

return num | (1 << pos);


}

int main()

int num = 0b10110110; // 182

int pos = 2;

int newNum = setBit(num, pos);


printf("New number after setting bit %d: %d (Binary: %08b)\n", pos, newNum, newNum);
return 0;

}
Explanation:

• 1 << pos creates a mask with 1 at the given position.

• num | (1 << pos) ensures that bit remains 1 even if it was already 1.

Example Output:
New number after setting bit 2: 182 (Binary: 10111110)

3. Clearing a Bit

This clears a particular bit (sets it to 0) without affecting other bits.

#include <stdio.h>

int clearBit(int num, int pos)

return num & ~(1 << pos);


}

int main()

int num = 0b10110110; // 182

int pos = 5;
int newNum = clearBit(num, pos);

printf("New number after clearing bit %d: %d (Binary: %08b)\n", pos, newNum, newNum);
return 0;
}

Explanation:

• 1 << pos creates a mask with 1 at the target position.

• ~(1 << pos) flips all bits except the target bit.

• num & ~(1 << pos) forces the bit to be 0.

Example Output:
New number after clearing bit 5: 150 (Binary: 10010110)

4. Toggling a Bit
This flips a bit (from 0 to 1 or 1 to 0).
#include <stdio.h>

int toggleBit(int num, int pos)

return num ^ (1 << pos);


}

int main()

int num = 0b10110110; // 182

int pos = 3;

int newNum = toggleBit(num, pos);

printf("New number after toggling bit %d: %d (Binary: %08b)\n", pos, newNum, newNum);

return 0;
}

Explanation:

• 1 << pos creates a mask at the target bit.

• num ^ (1 << pos) flips that bit.

Example Output:

New number after toggling bit 3: 174 (Binary: 10101110)

5. Counting the Number of Set Bits (Hamming Weight)


This counts how many 1s are present in a number.

#include <stdio.h>

int countSetBits(int num)

int count = 0;

while (num)
{

count += num & 1; // Check LSB

num >>= 1; // Right shift


}

return count;

}
int main()

int num = 0b10110110; // 182

printf("Number of set bits: %d\n", countSetBits(num));


return 0;

Explanation:

• num & 1 checks if the least significant bit (LSB) is 1.

• num >>= 1 shifts bits right, checking one bit at a time.

Example Output:

Number of set bits: 5

6. Checking if a Number is Power of 2

This determines if a number is a power of 2 (i.e., only one bit is set).

#include <stdio.h>

int isPowerOfTwo(int num)

{
return (num > 0) && ((num & (num - 1)) == 0);

}
int main()
{

int num = 16;

if (isPowerOfTwo(num))

printf("%d is a power of 2\n", num);

else

printf("%d is NOT a power of 2\n", num);


return 0;

Explanation:
• A power of 2 has only one 1 bit (e.g., 0001, 0010, 0100).

• num & (num - 1) removes the lowest 1 bit.


If the result is 0, it's a power of 2.
Example Output:

16 is a power of 2

7. Reversing Bits of an Integer


This reverses the binary representation of a number.

#include <stdio.h>

unsigned int reverseBits(unsigned int num)

unsigned int rev = 0;

for (int i = 0; i < 8; i++)

{ // Assume 8-bit number

rev |= ((num >> i) & 1) << (7 - i);


}

return rev;

int main()

{
unsigned int num = 0b10110110; // 182

printf("Reversed bits: %d (Binary: %08b)\n", reverseBits(num), reverseBits(num));


return 0;
}

Explanation:

• Extract each bit and place it in the reverse position.

Example Output:

Reversed bits: 109 (Binary: 01101101)

Bit manipulation is heavily used in embedded systems for efficient low-level programming. Here are some
real-world examples where bitwise operations are used:

1. Setting, Clearing, and Toggling GPIO Pins

Use Case:
Embedded systems often control GPIO (General Purpose Input/Output) pins for interfacing with sensors,
LEDs, motors, etc.

Example:

#define GPIO_PORT (*(volatile unsigned int*)0x40021000) // Example GPIO Register

#define LED_PIN (1 << 5) // LED connected to bit 5

void turnOnLED()

{
GPIO_PORT |= LED_PIN; // Set bit 5 (Turn ON LED)

void turnOffLED()
{

GPIO_PORT &= ~LED_PIN; // Clear bit 5 (Turn OFF LED)

void toggleLED()
{

GPIO_PORT ^= LED_PIN; // Toggle bit 5 (Flip LED state)

Explanation:

• |= (OR) sets the bit to 1 (turns LED ON).

• &= ~ (AND with NOT) clears the bit to 0 (turns LED OFF).

• ^= (XOR) toggles the bit (switches LED state).

2. Checking if a Bit is Set (Reading Sensor Status)

Use Case:

Reading button press or sensor status from an input pin.

Example:

#define GPIO_PORT (*(volatile unsigned int*)0x40021000) // Example GPIO Register

#define SENSOR_PIN (1 << 3) // Sensor connected to bit 3

int isSensorActive()
{
return (GPIO_PORT & SENSOR_PIN) ? 1 : 0; // Check if bit 3 is HIGH

}
Explanation:

• & (AND) is used to check if a specific bit (SENSOR_PIN) is set (1).

• If set, it returns 1 (sensor is active), else 0.

3.Efficient Data Packing in Embedded Systems

Use Case:

Reducing memory usage by storing multiple values in a single variable.

Example:

Storing sensor data (temperature, pressure, humidity) in a single 32-bit integer.

#include <stdio.h>

void packData(int *data, int temp, int pressure, int humidity)

{
*data = (temp & 0xFF) | ((pressure & 0xFF) << 8) | ((humidity & 0xFF) << 16);

void unpackData(int data, int *temp, int *pressure, int *humidity)

*temp = data & 0xFF;


*pressure = (data >> 8) & 0xFF;

*humidity = (data >> 16) & 0xFF;


}
int main()

int data;

packData(&data, 25, 101, 60); // Store values

int t, p, h;

unpackData(data, &t, &p, &h); // Extract values


printf("Temp: %d, Pressure: %d, Humidity: %d\n", t, p, h);

return 0;

}
Explanation:

• Packing: Uses | (OR) and bit shifts to combine values.

• Unpacking: Uses & (AND) and bit shifts to extract values.


4. Using Bit Fields in Structs to Optimize Memory

Use Case:

In embedded systems, memory is limited. Bit fields allow packing multiple values into a single byte.
Example:

#include <stdio.h>

struct DeviceStatus

unsigned int power : 1; // 1 bit

unsigned int error : 1; // 1 bit

unsigned int mode : 2; // 2 bits (00, 01, 10, 11)

};
int main()

struct DeviceStatus status = {1, 0, 2}; // Power ON, No Error, Mode 2

printf("Power: %d, Error: %d, Mode: %d\n", status.power, status.error, status.mode);

return 0;
}

Explanation:
• Saves memory by using only the required bits instead of whole bytes.

Conclusion

Mastering bit manipulation is crucial in embedded systems and low-level programming. It optimizes
performance, reduces memory usage, and enhances hardware interaction. By practicing the above problems,
you’ll gain proficiency in handling bit-level operations efficiently.

You might also like