November 22, 2024

Binary Representation (Transformation) of Integers in C/C++


In this C/C++ tutorial, you will learn:

  1. What is a bit-wise logical AND operator in C/C++
  2. What is a bit shift operator in C/C++
  3. How to transform integers into a binary form in C/C++. For example, you will learn how to transform an integer 21 into its binary 8-bit form. The result is 0001\;\; 0101.

The main motivation for creating this post comes from the coding of microcontrollers and FPGAs. Namely, in microcontrollers and FPGAs, registers are used to store a bit pattern. On the other hand, in the high-level coding languages that are used to program microcontrollers and FPGAs, integer representations of bit patterns are used. Consequently, if you want to program your microcontroller or an FPGA by using C/C++, it is very important to know how to transform integers into a series of bits. The YouTube tutorial accompanying this page is given below.

Bit Representation of Unsigned Integers

Let us assume that we want to represent an unsigned integer as an 8-bit binary number. For example, let us consider the number 21. This number has the following binary representation:

(1)   \begin{align*}21 & = 1\cdot 2^{4}+5 \\21 & = 1\cdot 2^{4}+1\cdot 2^{2} +1 \\21 & =1\cdot 2^{4}+1\cdot 2^{2}+1\cdot 2^{0}=16+4+1 \end{align*}



From the last expression, we have that:

  • The bit at the position (0+1) is equal to 1
  • The bit at the position (2+1) is equal to 1
  • The bit at the position (4+1) is equal to 1

where the position is measured from the right (from the least significant bit) and all the other bits are equal to zero. This gives us the following binary representation of the number 21

(2)   \begin{align*}21 & = 0001\;\; 0101\end{align*}

Bit-wise logical AND

Bit-wise logical AND is best explained by using an example. Consider two numbers in the binary representation

(3)   \begin{align*}A=  1001\;\; 0101  \\B=  0011\;\; 0001 \end{align*}

As its name suggests, the bit-wise logical AND is applied element-wise. This operator is denoted by \&. We have

(4)   \begin{align*}A \& B = 0001\;\; 0001\end{align*}

That is, we take the bits of A and B with the same significance (with the same position), and we apply a logical AND to these bits.

Bit Shift Operator in C/C++

Next, we explain the bit shift operator in C/C++. The left bit shift operator is denoted by <<. It is a binary operator that shifts the bits of the left operand for the number of bits represented by the right operand. For example, consider the following binary number A=0010\;\; 0100. The results of applying the following operation on A is

(5)   \begin{align*}A<<2 = (0010\;\; 0100)<<2= 1001 \;\; 0000\end{align*}

In the same manner, we can define the right bit shift operator >>.

Transformation of Integers to Binary Numbers in C/C++

Now that we know what are bit-wise AND and bit shift operator, we can explain how to transform an unsigned integer to a binary number. First, we need to observe that a binary number with only a single non-zero bit can uniquely be represented by using a binary number with only a least significant bit and a shift operator. For example

(6)   \begin{align*}0100\;\; 0000 = 0000\;\; 0001 << 6 \\0001\;\; 0000 = 0000\;\; 0001 << 4 \\0000\;\; 0100 = 0000\;\; 0001 << 2 \end{align*}

Now, let us consider the number A=21 in the decimal base. Its binary representation is A= 0001\;\; 0101. We will show that we can create this binary representation by only using the number 0000\;\; 0001, left bit shift operator, and the bit-wise logical AND operator. Consider the following operation

(7)   \begin{align*}A \& 0000 \;\; 0001\end{align*}

This will obviously produce

(8)   \begin{align*}A \& 0000 \;\; 0001 = 0000 \;\; 0001\end{align*}

This means that A has a non-zero bit at position 1 (least significant bit). Here it should be emphasized that in C/C++ A is usually declared as an unsigned integer. If we apply A \& 0000 \;\; 0001, C/C++ considers A as a binary number, although it is originally declared as an unsigned integer.

On the other hand, consider the number B=20. Its binary representation is 0001 \;\; 0100. Then we have,

(9)   \begin{align*}B \& 0000 \;\; 0001 = 0000 \;\; 0000\end{align*}

This means that B has a zero bit at the position 1 (least significant bit). From this, we conclude

IF ( (NUMBER \& 0000 \;\; 0001) == 0000 \;\; 0001 )
THEN NUMBER has 1 at the position of the first bit, OTHERWISE it has 0 at the position of the first bit.

where NUMBER is an unsigned integer. In this way, we can extract the bit at the first position. Note here again that NUMBER is declared as an unsigned integer in C/C++, and C/C++ internally considers it as a binary number while performing bit-wise logical operations. Let us go back to our original example of the number A, and let us explain how to extract the bit at the second position. Obviously, we have

(10)   \begin{align*}A \& 0000 \;\; 0010 = 0000 \;\; 0000\end{align*}

This is because A does not have 1 bit at the second position. On the other hand, the last expression can be written as follows

(11)   \begin{align*}A \& (0000 \;\; 0001<<1) = 0000 \;\; 0000\end{align*}

That is, we can use the left bit shift operator and 0000 \;\; 0001 to perform this logical statement. This generalized to

IF ( (NUMBER \& (0000 \;\; 0001<< 1 )) == (0000 \;\; 0001<< 1) )
THEN NUMBER has 1 at the position of the second bit, OTHERWISE it has 0 at the position of the second bit.

In this way, we can extract the second bit.

In the general case, we have

IF ( (NUMBER \& (0000 \;\; 0001<< N )) == (0000 \;\; 0001<< N) )
THEN NUMBER has 1 at the position of the (N+1)th bit, OTHERWISE it has 0 at the position of the (N+1)th bit.

In this way, we can extract the (N+1)th.

That is, we learned that by only using AND, left shift bit operators, and 0000 \;\; 0001 we can transform integer representations into binary representations.

C/C++ code

Here is the C/C++ code to perform the transformation.

#include <stdio.h>
#include <stdint.h>


int main()
{
 uint8_t a;
 uint8_t shiftedNumber;
 uint8_t result;
 uint8_t oneConstant=1;
 bool bitValue;

 a=55;
 printf("%u \n",a); 

 for (unsigned int i=8;i>0;i--)
 {
 	shiftedNumber=oneConstant<<(i-1); // shift 1 (i-1) places, for example i=8, 1<<(7) = 1000 0000
    result = a & shiftedNumber; // this will return shiftedNumber if a has the bit that is equal to the non-zero bit of shiftedNumber
    bitValue = (result==shiftedNumber) ? 1 : 0;
 	printf("%d",bitValue);
 }

}

This code will produce 00110111, and that is exactly the 8-bit representation of the input number a=55. The code is self-explanatory, except for the data type uint8_t. This is an unsigned 8-bit integer that is defined in the header file “stdint.h”. The explanation of this header file is given here.