Q

Emertxe-News & Blog

Home » C programming » Bitwise operators in C – common mistakes and how to avoid them
Bitwise operators in C – common mistakes and how to avoid them
An operator that performs operation on a “bit-level” is said to be bit-wise operator. Generally, bitwise operators in C operate on a single bit at a time. Though it operates on a bit at a time, it needs one byte as input. C provides six bit-wise operators.

Need for Bit-wise operator

In low level programming on embedded systems, to set, clear or toggle a single bit of a specific register without modifying other bits, we need bit-wise operators. Bit-wise operations in C are faster than usual add, divide and multiplication in a low-cost processor, whereas in modern processors +, *, / are as fast as bitwise operators. Bit-wise operation utilizes less power due to reduced use of resources. Bit-wise operators in C are used to manipulate values for comparisons and calculations.

Bit-wise operators

Operators Bit-wise Operation Bit-wise Assignment operators
&
Bitwise AND operator
Logical AND operation will be performed, when “&” is applied. For any given input, if any of the input bit is low, corresponding output bit will be low. Only if both input bits are high, output bit will be high.
E.g.
10001000
10000001
    &
10000000
&=
|
Bitwise OR operator
Logical OR operation will be performed, when “|” is applied. For any given input, if any of the input bit is high, corresponding output bit will be high. Only when both input bits are low, output bit will be low.
E.g.
10001000
10000001
    |
10001001
|=
^
Bitwise XOR operator
It is equivalent to adding two bits and discarding the carry. If two bits are not similar, output is high. If two bits are similar, output is low. XOR can be used to toggle bits between 1 and 0.
E.g.
10001000
10000001
    ^
00001001
^=
~
Bitwise NOT operator
Bit-wise NOT gives complement of given number. Simply, the bits are inverted.
E.g.
  x = 10001000
~x = 01110111    ~
~=
>>
Right shift operator
Right shift shifts each bit in its left operand to the right. The number followed by the operator decides the number of places the bits are shifted. Right shift is nothing but diving a bit pattern by 2. Finally, the blanks are filled by zero.

E.g.

Empty bit locations should be filled depending upon the modifier associated with the basic integral data type.

Case 1: signed char / signed int

When a number is shifted right, empty bit locations will be filled with the MSB bit of that particular number. In the below given example, MSB bit is 1. Hence, empty bit location is filled with 1.

x = 11100111 >> 1
       11110011

Case-2: Unsigned char / Unsigned int

When a number is shifted right, empty bit locations will be always filled with the 0’s only.

x = 11100111 >> 1
       01110011

>>=
<<
Left shift operator
Left shift shifts each bit in its left operand to the left. Number followed by the operator decides the number of places the bits are shifted. Left shift is nothing but multiplying a bit pattern by 2. Finally, the blanks are filled by zero.
E.g.
x = 11100111 << 1
      11001110
<<=

MISTAKES PROGRAMMERS DO WITH BITWISE OPERATORS

1. Mixing bit-wise and relational operator in the same full expression can be a sign of logic error.

#include<stdio.h>
int main()
{
   int x = 6, data;
   data = (x == 6|2);
   printf("%d",data);
   return 0;
}

Fig 1: Operator precedence error

In the above example, (|) OR takes higher precedence than ==, so the output will be wrong. We will get it as 3.

Output

bitwise-operators-in-C

Fig 1.1 : Error output

Correct code

#include<stdio.h>
int main()
{
   int x = 6, y, data;
   y = 6|2;
   if(x == y)
   {
      data = x;
      printf("%d",data);
   }
   return 0;
}

Fig 2: Operator precedence error corrected

In the above code, OR operation is performed at first and then comparison occurs. So the required output is obtained.

Output

bitwise-operators-in-C

Fig 2.1 : Correct output

2. Operator precedence between Ternary operator and bit-wise operator

In this example, we need ternary operator’s evaluated answer to be ORed with 0x80 and then output should be printed. Due to high precedence “|” will be done at first and then ternary operator is evaluated.

#include<stdio.h>
int main()
{
  int data = 1;  //data can be anything
  printf("%d", 0x80 | data ? 0x3: 0x2);
  return 0;
}

Fig 3: Operator precedence error

Output

bitwise-operators-in-C

Fig 3.1 : Error output

Correct code

#include<stdio.h>
int main()
{
   int data = data ? 0x3 : 0x2;
   printf("%d", 0x80|data);
   return 0;
}

Fig 4: Operator precedence error corrected

This code will provide the expected output. As ternary operation is performed at first and then the OR operation.

Output

bitwise-operators-in-C

Fig 4.1 : Correct Output

3. Left shift / Right shift beyond the size of the variable will lead to undefined behavior and also they should not be used for negative numbers.

E.g.

 int j = 1;  
 j << 33, j>> 33	// both are incorrect

Here, variable “j” is of type integer where its size is 32bits. When we try to shift it to 33rd bit position we will get an error.

For example,

if a = -1;
   a << 1	(-1 << 1)	//undefined behavior
   1 << a 	(1 << -1)	//undefined behavior

We can neither shift a negative number nor get a number shifted by negative number.

4. Bitwise operators in C should not be used with variable of type float. It is because they are stored in IEEE format (sign bit, exponent and mantissa). Using shift operators with variables of type float / double causes changes in exponent leading to incorrect result.

5. Inputs should not be provided in binary form

Inputs in binary form with bitwise operator will provide wrong answer.  Bit-wise operators are to operate at bit level. So we don’t have to provide bits.

#include<stdio.h>
int main()
{
  int a = 0010, b = 0001;
  c = a ^ b;
  printf("%d",c);
  return 0;
}

Fig 5: Input error

Output

bitwise-operators-in-C

Fig 5.1 : Error output

The above code provides 9 as output whereas 3 is the answer.

Correct code

#include<stdio.h>
int main()
{
  int a = 2, b = 1, c;
  c = a ^ b;
  printf("%d",c);
  return 0;
}

Fig 6: Inputs given in decimals

In the below example, inputs are provided in decimal format so that its bits will be XORed with each other and the correct output will be provided.

Output

bitwise-operators-in-C

Fig 6.1 : Correct Output

Conclusion

There are quite a few errors possibly made with precedence and bitwise operators in C. Above examples 1 and 2 are two from that possible errors. Other than precedence we should learn where and how to use a bitwise operator in C programming. Before using the bit-wise operators, one should learn the limitations of the operators and then put it into use, so that the errors can be minimized.

YOU MAY ALSO LIKE

Emertxe’s Online Training Programs in Embedded Systems & IoT

Emertxe’s Online Training Programs in Embedded Systems & IoT

The reason why Emertxe is the best choice for career advancement: eLearning and Online training programs are the way forward in the COVID-19 disrupted world. Riding along the digital revolution will ensure engineers are future-ready with skills to not only secure but...

Our Training Programs for Freshers

Our Training Programs for Freshers

Introduction: Emertxe is the leading training institute in Bangalore for Embedded Systems and IoT domains. It is a pioneer in training freshers since 2003 by providing excellent placement opportunities for freshers. Over the years 70000+ students have made their...

Q