**Topic :**Bit-wise Logical Operators

**Author :**GHA

**Page :**

**1**Next >>

**Bit-wise Logical Operators**

Besides representing a number or a character, a memory location can be used for various purposes as a set of bits. For example, individual bits in a byte can represent "flags" that identify the propertyires or current state of an object or program. Combinations of bits may represent "fields" packed into one int or long memory location. Idividual bits may also represent pixels in an image, and bit patterns may be used in low-level routines for programming hardware registers.

Variables used as sets of bits can be declared as unsigned integral types. It makes sense to distinguish these variables from numeric and character variables by introducing special data types for them. The following data type names have become rather common:

typedef unsigned char BYTE;

typedef unsigned short WORD;

typedef unsigned long DWORD; // "double word"

A BYTE variable has eight bits. To make our discussion more concrete, let's assume that a WORD has two bytes (16 bits) and a DWORD, four bytes (32 bits). The individual bits are oten referred to by their positi9ons in a byte or a word, starting from 0 at the rightmost, least significant bit. For example, bits in a byte would be numbered 0 through 7 as is below (this is the usual numbering of bits in a byte):

Bit 7 6 5 4 3 2 1 0

0 1 0 0 1 1 0 1

|_|_|_|_|_|_|_|_|

The easiest way to initialize variables that represent bit patterns in C++ is by using hexadecimal numbers. Eash hex digit corresponds to four bits, as follows:

__Binar__

__Hex__

0000 0

0001 1

0010 2

0011 3

0100 4

0101 5

0110 6

0111 7

1000 8

1001 9

1010 A

1011 B

1100 C

1101 D

1110 E

1111 F

C++ allows you to write a hex constant as a sequence of hex digits preceded by 0x. For example:

WORD flags = 0x8020; // 1000 0000 0010 0000

WORD mask = 0xFFC0; // 1111 1111 1100 0000

BYTE data_ready_bit = 0x20; // 0010 0000

A byte can be defined by two hex digits, a word by four hex digits, and a double word by eight hex digits.

It is useful to remember hex equivalents for the following bit patterns:

__Binar__

__Hex__

00000000 0x00 (or just 0)

00000001 0x01

00000010 0x02

00000100 0x04

00001000 0x08

00010000 0x10

00100000 0x20

01000000 0x40

10000000 0x80

11111111 0xFF

11110000 0xF0

00001111 0x0F

0000000000000001 0x0001

...

1000000000000000 0x8000

1111111100000000 0xFF00

0000000011111111 0x00FF

1111111111111111 0xFFFF

C++ offers four bit-wise logical operators: the binary operators "and," "or," and "xor," and a unary operator "not." These operators take operands of integral types, but the values of individual bits in the result are determined by the vlue of corresponding bits (bits in the same positions) in operands.

The "and" operator is denoted by the symbol '&'. In the & operation the resulting bit is 1 if and only if both corresponding bits in the two operands are 1.

For example:

00010100 11100010

& 11111111 00000000

-----------------

00010100 00000000

Or, in hex representation:

0x14E2 & 0xFF00 = 0x1400

The "or" operator is denoted by the symblo '|'. In the | operation, the resulting bit is 1 if and only if at least on of the corresponding bits in the two operands is 1.

For example:

00010100 00010001

| 00000000 00111111

-----------------

00010100 00111111

Or, in hex representation:

0x1411 | 0x003F = 0x14003F

The "xor" operator is denoted by the symbol '^'. In the ^ operation the resulting bit is 1 if and only if exactly one of the corresponding bits in the two operands is 1.

For example:

00010100 11110001

^ 00000000 11111111

-----------------

00010100 00001110

Or, in hex representation:

0x14F1 ^ 0x00FF = 0x140E

The "not" operator is a unary operator. It is denoted by '~'. In the ~ operation the resulting bit is set to 1 if the corresponding bit in the operand is 0 and to 0 if the corresponding bit in the operand is 1.

For example:

~ 00001111 00000001

-----------------

11110000 11111110

Or, in hex representation:

~0x0F01 = F0FE

&, |, and ^ have lower precendence than relational operators, including the == and != operators.

For example:

... (x & 0x0001 !=0)

is interpreted as:

... (x & (0x0001 != 0))

as opposed to the possible intended:

... ((x & 0x0001) != 0)

This is a potential source of nasty bugs. Its is always safer to use parentheses around binary bitwise operators.

The &, |, and ^ operators can be used in compound assingments. For Example:

WORD flags = 0x0020;

flags |= 0x8000; // same as: flags = flags | 0x8000;

flags &= 0x00C0; // same as: flags = flags & 0x00C0;

The & operator can be used to test or reset a bit in a byte or word. For example:

BYTE flag = 0;

const BYTE data_ready_bit = 0x20;

...

if (flags & data_ready_bit) // Test the "data ready" bit

...

...

flags &= ~data_ready_bit; // Reset the "data ready" bit (to 0)

& can also be used to set a bit in a byte or word. For example:

flags |= data_ready_bit; // Set "data ready" bit to 1

the ^= operator is handy when you need to toggel a bit or a value. The following function calculates the alternating sum of numbers in an array and uses ^= to toggel the sign flag.

double AlernatingSum(const gvector &x) {

// Returns x[0] - x[1] + x[2] - x[3] + ... - (or +) x[n-1].

double sum=0.;

**Page :**

**1**Next >>