------------------------------------------------
         "Bit Operators in Practice"
------------------------------------------------
  C/O :: arp of DynamicHell Development Team
------------------------------------------------
  http://dynamichell.org | irc.dynamichell.org
------------------------------------------------

Note
====

It must be noted that this tutorial is aimed at users with a basic understanding
of binary.


Introduction
============

As a C/C++ programmer you will have become familiar with various means of 
manipulating data.  However, it is highly likely that the smallest unit you have
so far dealt with is a byte which size is defined by the constant CHAR_BIT.  It 
must be noted that CHAR_BIT is always guaranteed to be greater-than or equal
to 8 bits in size; on various architectures and operating systems this size does
vary.  Though for all our purposes we will assume a CHAR_BIT to be 8 bits in 
size.  And with all examples 8-bit unsigned integers are used.  

You may have wondered whether or not it is possible to manipulate the individual
bits in an integer, long, char or short.  The answer is yes.

There are many uses for bitwise operators, but perhaps the most common is the 
use of a single integer or long to store various flags.  Rather than store each 
value in a seperate variable, each option can be assigned a bit in a single 
integer.  Much more efficient!

C and C++ provide the programmer with six means of manipulating individual bits
within an integer, long, char or short.  These are appropriately named 
operators.  The six operators for manipulating bits follow:

Operator     Description
--------     ---------------------
   &         Bitwise AND operator
   |         Bitwise OR operator
   ^         Bitwise XOR operator
   ~         Bitwise NOT operators
   <<        Left-shift operator
   >>        Right-shift operator
   
Each of these operators serves a different function to the programmer.  

Note: The short, long, int and char data types that you are manipulating
are called operands.

This tutorial aims to introduce bit operators, operands and their usage.


The Bitwise AND Operator
========================

The bitwise & operator works by comparing each bit in operand x with operand y.
If both bits are 1 (on) then 1 is placed in the same bit in the result.  
However, if one or two of the bits are 1 (on) then 0 is placed in the same bit 
in the result.

Example:

z = 7 & 3
z = 0000 0111 & 0000 0011
 
  0000 0111
& 0000 0011
  ---------
  0000 0011
 
Therefore 3 = 7 & 3.

The & operator is commonly used to turn bits off in the result which are on
in x but not on in y.  As the third bits from the left show in the above 
example.

The & operator is also often used to see whether the bits in x, match the bits 
set in y.  For example to test whether bits 1 and 2 (from the left) are set in 
operand x you would use the following statement:

if(x & 3)                             /* if(x & 0000 0000 0000 0011) */                       
  puts("Bits one and two are set.");
else
  puts("Bits one and two are not set.");



The Bitwise OR Operator
=======================

The bitwise | operator works by comparing each bit in operand x with operand y.
If either bit is 1 (on) then 1 is placed in the result.  The same also applies
if both bits are 1 (on).

The | operator is commonly used to set bits that are on in operand y but not in
operand x.  For example, to set bits 2 and 3 (from the left) on in x you would 
use the following assignment.

z = 9 | 6
z = 0000 1001 | 0000 0110

  0000 1001
| 0000 0110
  ---------
  0000 1111

Therefore, 15 = 9 | 6.


The Bitwise XOR Operator
========================

The bitwise ^ operator works by comparing each bit in operand x with operand y.
If either bit, but not both, is 1 (on) then 1 is placed in the result.

Example:

z = 7 ^ 3
z = 0000 0111 ^ 0000 0011

  0000 0111
^ 0000 0011
  ---------
  0000 0100

Therefore, 4 = 7 ^ 3.


The Bitwise NOT Operator
========================

The bitwise ~ operator works with only one operand.  Each bit in the operand is
reversed.  So that 1 (on) becomes 0 (off), and 0 becomes 1.

Example:

z = ~(7)
z = ~(0000 0111)

~ 0000 0111
  ---------
  1111 1000

Therefore, 248 = ~7.  Of course we are assuming the use of two 8-bit integers.


The Left-Shift Operator
=======================

The << operator works by shifting the bits of an operand so many bits to the 
left.  To shift x by y bits to the left you would use the statement x << y.

Example:

Where    : x = 12;
Statement: x << 3;

  0000 1100 << 3
  ---------
  0110 0000

Therefore, if x = 12 and x << 3 then x = 96.


The Right-Shift Operator
========================

The >> operator works by shifting the bits of an operand so many bits to the 
right.  To shift x by y bits to the right you would use the statement x >> y.

Example:

Where    : x = 96;
Statement: x >> 3;

  0110 0000 >> 3
  ---------
  0000 1100
  
Therefore, if x = 96 and x >> 3 then x = 12.


Example Code
============

The following includes example code which can be built to aid the understanding
of bitwise and bitshift operators.

/* bitwise_and.c */

#include <stdio.h>
#include <stdlib.h>


int main(void)
{
    unsigned int x = 7, y=3, z=0;
    
	puts("\nThe bitwise AND operator (&) places 1 in the result if ");
	puts("both operands are 1.  0 is placed in the result if either");
	puts("operands are 0.\n");
	puts("x = 0111, y = 0011, z = 0000");
	puts("----------------------------");
	puts("With z = x & y (z = 0111 & 0011)");	
	puts("z should equal 0011");
	puts("----------------------------");
	z = x & y;
	printf("z = %u\n\n",z); 
	
	return EXIT_SUCCESS;	
}

/* End of bitwise_and.c */


/* bitwise_or.c */

#include <stdio.h>
#include <stdlib.h>


int main(void)
{
    unsigned int x = 9, y=6, z=0;
    
	puts("\nThe bitwise OR operator (|) places 1 in the result if ");
	puts("either operand, including both, is 1.\n");
	puts("x = 1001, y = 0110, z = 0000");
	puts("----------------------------");
	puts("With z = x | y (z = 1001 | 0110)");	
	puts("z should equal 1111");
	puts("----------------------------");
	z = x | y;
	printf("z = %u\n\n",z); 
	
	return EXIT_SUCCESS;	
}

/* End of bitwise_or.c */


/* bitwise_xor.c */

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    unsigned int x = 7, y=3, z=0;
    
	puts("\nThe bitwise XOR operator (^) places 1 in the result if ");
	puts("either  operands are 1, but not both.\n");
	puts("x = 0111, y = 0011, z = 0000");
	puts("----------------------------");
	puts("With z = x ^ y (z = 0111 ^ 0011)");	
	puts("z should equal 0100");
	puts("----------------------------");
	z = x ^ y;
	printf("z = %u\n\n",z); 
	
	return EXIT_SUCCESS;	
}

*/ End of bitwise_xor.c */


/* biwise_not.c */

#include <stdio.h>
#include <stdlib.h>


int main(void)
{
    unsigned short x = 9; /* 16-bit unsigned integer on 32-bit integer systems.*/
    
	puts("\nThe bitwise NOT operator (~) reverses each bit in the operand. ");
	puts("Thus, only one operand is used.\n");
	puts("x = 0000000000001001 = 9");
	puts("------------------------------------");
	puts("With x = ~x (x = ~0000000000001001)");	
	puts("                  ----------------");
	puts("               =  1111111111110110");
	puts("------------------------------------");
	x = ~x;
	printf("Inverted x = %u and inverted again\n",x); 
	x = ~x;
	printf("~x = %u\n\n",x); 
	return EXIT_SUCCESS;	
}

/* End of bitwise_not.c */


/* bitshift.c */

#include <stdio.h>
#include <stdlib.h>


int main(void)
{
  unsigned int x = 12;
  unsigned int y = 3;

  puts("Here x is 12 and y is 3");
  printf("x << y is %u\n",x << y);
  printf("Here x is %u and y is %u\n",x,y);
  printf("x >> y is %u\n",x >> y);	
	
  return EXIT_SUCCESS;	
}

*/ End of bitshift.c */



Copright (c) 2005.  Alastair Poole.

Verbatim copying and distribution of this entire article are permitted
worldwide, without royalty, in any medium, provided this notice, and the
copyright notice, are preserved.
