CSC373 Sep13

slide version

single file version

Contents

  1. Bit Operations on integer types
  2. Bitwise and
  3. Left shift
  4. Right shift for the unsigned int data type
  5. Right shift for the int data type
  6. Right Shift (cont.)
  7. !, the bang operator
  8. ! Operator Examples
  9. Unsigned addition
  10. Carry out of leftmost bit
  11. A C function getLSByte(int x)
  12. A C function getMSByte(int x)
  13. Datalab
  14. Bit Operation FAQs

Bit Operations on integer types[1] [top]

Operator     name               binary/unary
&            bitwise and          binary  
|            bitwise or           binary
^            bitwise xor          binary
~            1's complement       unary
<<           left shift           binary
>>           right shift          binary

Bitwise and[2] [top]



unsigned char x = 0x1C;
unsigned char y = 0x95;
In binary x's value:  00011101
          y's value:  10010101
          ---------- ---------
          x & y    :  00010101

In hex x's value: 0x1C
       y's value: 0x95
       ---------  --
       x & y      0x15

(In decimal, x & y = 21.)

   

Left shift[3] [top]



int x = 0x1000801F;
In binary x's value:  0001 0000 0000 0000 1000 0000 0001 1111
          ---------- ----------------------------------------
          x << 3   :  1000 0000 0000 0100 0000 0000 1111 1000

In hex the value of x << 3 is: 0x800400F8

The left shift operation, x << n is performed by starting with a copy
of the bits of x, then shifting them left n bits. The leftmost n bits
have nowhere to go and are discarded. The rightmost n bits are filled
with 0's.  

Right shift for the unsigned int data type[4] [top]



unsigned int x = 0x800400F8;

In binary x's value:  1000 0000 0000 0100 0000 0000 1111 1000
          ---------- ----------------------------------------
          x >> 3   :  0001 0000 0000 0000 1000 0000 0001 1111

In hex the value of x >> 3 is: 0x1000801F

The right shift operation for unsigned int's, x >> n, is performed by
starting with a copy of the bits of x, then shifting them right n
bits. The rightmost n bits have nowhere to go and are discarded. The
leftmost n bits are filled with 0's. Filling the leftmost n bits with
0's is also called "logical right shift".

Right shift for the int data type[5] [top]

This operator works like the right shift for unsigned int's except for the way the left most bits are filled in.

Unfortunately, the C standard doesn't specify which of two possible meanings should be used. Consequently, some compiler implementations might choose one meaning, while other compilers, the other meaning.

One meaning of right shift for signed int's is just the same as for unsigned int's. This is called logical right shfit.

The other meaning of right shift for signed int's is called arithmetic right shift. It is described next:

Right Shift (cont.)[6] [top]



int x = 0x800400F8;

In binary x's value:  1000 0000 0000 0100 0000 0000 1111 1000
          ---------- ----------------------------------------
          x >> 3   :  1111 0000 0000 0000 1000 0000 0001 1111

In hex the value of x >> 3 is: 0xF000801F

But,

int y = 0x700400F8;

In binary y's value:  0111 0000 0000 0100 0000 0000 1111 1000
          ---------- ----------------------------------------
          y >> 3   :  0000 1110 0000 0000 1000 0000 0001 1111

In hex the value of y >> 3 is: 0x0E00801F

The arithmetic right shift operation for signed int's, x >> n, is performed by
starting with a copy of the bits of x, then shifting them right n
bits. The rightmost n bits have nowhere to go and are discarded. The
leftmost n bits are filled with the a copy of the left most bit of x. 

!, the bang operator[7] [top]

In C, there is no boolean data type; C++ added the bool type.

Numeric expressions occurring as if or while conditions are implicitly interpreted as logical true or logical false.

A value of 0 is interpreted as false, while non-zero is interpreted as true.

The unary "bang" operator, !, as applied integers has a result which is either 0 or 1. For integers in a context where a boolean value is expected, the bang operator serves as logical negation.

At the bit level, the bang operator works like this: If any bit of x is non-zero, the result !x is 0. If all bits of x are 0, then !x is 1.

! Operator Examples[8] [top]



int x = 0x00008000

In binary x: 0000 0000 0000 0000 1000 0000 0000 0000
         !x: 0000 0000 0000 0000 0000 0000 0000 0000

More examples:
         x     !x
         --------
         0      1
         1      0
         2      0
        -1      0
      5280      0

If x is 4, what is !!x

Unsigned addition[9] [top]



 0 + 0 = 0
 0 + 1 = 1
 1 + 0 = 1
 1 + 1 = 10  (10 in binary is 2 in decimal)



E.g. unsigned byte integers
     x = 0x07
     y = 0x03

The sum is of course 10 or 0x0A in hex. 

In binary:

carry bits:      111   
	 x: 0000 0111
	 y: 0000 0011
	    ---------
       x+y: 0000 1010

or in hex x + y is 0x0A

Carry out of leftmost bit[10] [top]

If there is a carry out of the left most bit, it is simply discarded:

unsigned short a = 0xFFFF
unsigned short b = 0x0001

In binary:

carry bits:  11111 1111 1111 111
         a:   1111 1111 1111 1111
         b:   0000 0000 0000 0001
              -------------------
       a+b:   0000 0000 0000 0000
      
The carry bit out of the left most bit position, 1, is
discarded. So the result a + b is 0.

In decimal this result shows again that unsigned int type is different
from ordinary mathematical integers:

In decimal a: 65535 and b: 1

As unsigned short's 

           a + b = 0

Note that for signed integers this would mean a = -b = -1

That is, a = 0xFFFF  would be the hex representation of the signed
short integer -1.

A C function getLSByte(int x)[11] [top]

Use only 1 byte constants in your code.

Allowable operators: ! ~ & ^ | + << >>

int getLSByte(int x)

This function should return an integer with the least significant byte equal to the least significant byte of x and the other bytes should be 0.
Example: if x = 0x12345678, getLSByte(x) should return 0x00000078.


    1	int getLSByte(int x)
    2	{
    3	  int mask = 0x000000FF;
    4	  return x & mask;
    5	}

A C function getMSByte(int x)[12] [top]

Use only 1 byte constants in your code.

Allowable operators: ! ~ & ^ | + << >>

int getMSByte(int x)

This function should return an integer with the most significant byte equal to the most significant byte of x and the other bytes should be 0.
Example: if x = 0x12345678, getMSByte(x) should return 0x12000000.

How would you write this function?

Datalab[13] [top]

Components

Bit Operation FAQs[14] [top]

The bit operators have some properties that may be useful for the datalab where you are only allowed to use a small subset of operators to compute required values.

Here are some properties where x is assumed to be of type int (that is, a signed integer) of size 32 bits.

Expression =
0 ^ x x
(~0) ^ x ~x
x >> 31 0 if x >= 0, and ~0 if x < 0
if x == y what is x ^ y 0
When is !!x == x Only if x = 0 or x = 1
(x >> 31) ^ x x if x >= 0; ~x if x < 0