Bit By Bit

1. Convert following binary numbers into decimal numbers

1. 1111

Answer: 15

1 x 23 + 1 x 22 + 1 x 21 + 1 x 20 = 8 + 4 + 2 + 1 = 15

 

2. 1111 0000

Answer: 240

1 x 27 + 1 x 26 + 1 x 25 + 1 x 24 + 0 x 23 + 0 x 22 + 0 x 21 + 0 x 20

128 + 64 + 32 + 16 + 0 + 0 + 0 + 0 = 240

 

3. 1010 1011

Answer: 171

1 x 27 + 0 x 26 + 1 x 25 + 0 x 24 + 1 x 23 + 0 x 22 + 1 x 21 + 1 x 20

128 + 0 + 32 + 0 + 8 + 0 + 2 + 1 = 171

 

4. 1000 1000

Answer: 136

1 x 27 + 0 x 26 + 0 x 25 + 0 x 24 + 1 x 23 + 0 x 22 + 0 x 21 + 0 x 20

128 + 0 + 0 + 0 + 8 + 0 + 0 + 0 = 136

 

5. 1000

Answer: 8

1 x 23 + 0 x 22 + 0 x 21 + 0 x 20 = 8 + 0 + 0 + 0 = 8

 

6. 100

Answer: 4

1 x 22 + 0 x 21 + 0 x 20 = 4 + 0 + 0 = 4

 

7. 10

Answer: 2

1 x 21 + 0 x 20 = 2 + 0 = 2

 

8. 1

Answer: 1

1 x 20 = 1 = 1

 

 

2. What is the highest number that can be stored in 8 bits?

Answer: 255.

1111 1111 is the highest that can be stored.

1 x 27 + 1 x 26 + 1 x 25 + 1 x 24 + 1 x 23 + 1 x 22 + 1 x 21 + 1 x 20

128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 = 255

Alternately, the max number that can be stored can be calculated by

2n – 1, where n is the number of bits

Hence in 8 bits it will be 28 – 1 = 256 – 1 = 255

 

 

3. What is the highest number that can be stored in 9 bits?

Answer: 511

1 1111 1111 is the highest that can be stored.

1 x 28 + 1 x 27 + 1 x 26 + 1 x 25 + 1 x 24 + 1 x 23 + 1 x 22 + 1 x 21 + 1 x 20

256 + 128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 = 511

Alternately,

29 – 1 = 512 – 1 = 511

 

 

4. Convert following binary numbers into hexadecimal

1. 1101111100

Can be grouped into

11 0111 1100

From the table

0011 -> 3

0111 -> 7

1100 -> C

The hex notation will be

0x37C

 

2. 100000010000100

Can be grouped into

100 0000 1000 0100

From the table

0100 -> 4

0000 -> 0

1000 -> 8

0100 -> 4

The hex notation will be

0x4084

 

3. 11001100

Can be grouped into

1100 1100

From the table

1100 -> C

1100 -> C

The hex notation will be

0xCC

 

4. 1101001

Can be grouped into

110 1001

From the table

0110 -> 6

1001 -> 9

The hex notation will be

0x69

 

 

5. Convert following hexadecimal numbers into decimal and binary

1. 0xFF

1111 1111

15 x 161 + 15 x 160 = 240 + 15 = 255

 

2. 0xFF FF

1111 1111 1111 1111

15 x 163 + 15 x 162 + 15 x 161 + 15 x 160 = 61440 + 3840 + 240 + 15 = 65535

 

3. 0x10

0001 0000

1 x 161 + 0 x 160 = 16 + 0 = 16

 

4. 0xF0 00

1111 0000 0000 0000

15 x 163 + 0 x 162 + 0 x 161 + 0 x 160 =

61440 + 0 + 0 + 0 = 61440

 

 

6. Convert following decimal numbers into binary and hexadecimal

1. 128

Number Step Quotient Remainder
128 Divide by 2 64 0
64 Divide by 2 32 0
32 Divide by 2 16 0
16 Divide by 2 8 0
8 Divide by 2 4 0
4 Divide by 2 2 0
2 Divide by 2 1 0
1 Divide by 2 0 1

Binary: 1000 0000

Hex: 0x80

 

2. 15

Number Step Quotient Remainder
15 Divide by 2 7 1
7 Divide by 2 3 1
3 Divide by 2 1 1
1 Divide by 2 0 1

Binary: 1111

Hex: 0xF

 

3. 10

Number Step Quotient Remainder
10 Divide by 2 5 0
5 Divide by 2 2 1
2 Divide by 2 1 0
1 Divide by 2 0 1

Binary: 1010

Hex: 0xA

 

4. 40

Number Step Quotient Reminder
40 Divide by 2 20 0
20 Divide by 2 10 0
10 Divide by 2 5 0
5 Divide by 2 2 1
2 Divide by 2 1 0
1 Divide by 2 0 1

Binary: 10 1000

Hex: 0x28

 

5. 127

Number Step Quotient Reminder
127 Divide by 2 63 1
63 Divide by 2 31 1
31 Divide by 2 15 1
15 Divide by 2 7 1
7 Divide by 2 3 1
3 Divide by 2 1 1
1 Divide by 2 0 1

Binary: 111 1111

Hex: 0x7F

 

 

7. What is the result of following operations

1. 0x3B & 0xF0

0x3B 0 0 1 1 1 0 1 1
0xF0 1 1 1 1 0 0 0 0
& 0 0 1 1 0 0 0 0

Answer: 0x30

 

2. 0xFF & 0x01

0xFF 1 1 1 1 1 1 1 1
0x01 0 0 0 0 0 0 0 1
& 0 0 0 0 0 0 0 1

Answer: 0x01

 

3. 0xFF & 0x00

0xFF 1 1 1 1 1 1 1 1
0x00 0 0 0 0 0 0 0 0
& 0 0 0 0 0 0 0 0

Answer: 0x00

 

4. 0X87 & 0x78

0x87 1 0 0 0 0 1 1 1
0x78 0 1 1 1 1 0 0 0
& 0 0 0 0 0 0 0 0

Answer: 0x00

 

 

8. What would be the output of following program. Note %x prints integer as hexadecimal value.

#include <stdio.h>

int main(int argc, char * argv[]) {
    int operand1 = 0x42;
    int operand2 = 0x32;
    printf("0x%x & 0x%x = 0x%x \n", operand1, operand2, operand1&operand2);
    return 0;
}

 

Ans:

& operation on 0x42 and 0x32

0x42 0 1 0 0 0 0 1 0
0x32 0 0 1 1 0 0 1 0
& 0 0 0 0 0 0 1 0

Result is 0x02

The output of the program will be:

0x42 & 0x32 = 0x2

 

 

9. Explain the output of following program.

#include <stdio.h>
int main(int argc, char * argv[]) {
    int operand1 = 0x42;
    int operand2 = 0x32;
    printf("0x%x & 0x%x = 0x%x \n", operand1, operand2, operand1&operand2);
    printf("%u %u %u\n",sizeof(operand1), sizeof(operand2),sizeof(operand1&operand2));
    return 0;
}

 

Ans:

0x42 & 0x32 = 0x2

4 4 4

The first row of output is explained in previous question.

Second row prints size of int three times, once each for operand1 and operand2 and once for the result of & operation. Since result of & of two ints is an int, we see same value printed thrice.

 

 

10. What is the result of following operations

1. 0x3B | 0xF0

0x3B 0 0 1 1 1 0 1 1
0xF0 1 1 1 1 0 0 0 0
| 1 1 1 1 1 0 1 1

Answer: 0xFB

 

2. 0xFF | 0x01

0xFF 1 1 1 1 1 1 1 1
0x01 0 0 0 0 0 0 0 1
| 1 1 1 1 1 1 1 1

Answer: 0xFF

 

3. 0xFF | 0x00

0xFF 1 1 1 1 1 1 1 1
0x00 0 0 0 0 0 0 0 0
| 1 1 1 1 1 1 1 1

Answer: 0xFF

 

4. 0X87 | 0x78

0x87 1 0 0 0 0 1 1 1
0x78 0 1 1 1 1 0 0 0
| 1 1 1 1 1 1 1 1

Answer: 0xFF

 

 

11. Explain the output of following program.

#include <stdio.h>

int main(int argc, char * argv[]) {
    long operand1 = 0x100042;
    int operand2 = 0x2;

    printf("0x%lx | 0x%x = 0x%x \n", operand1, operand2, operand1|operand2);
    printf("%u %u %u\n",sizeof(operand1), sizeof(operand2),sizeof(operand1|operand2));
    return 0;
}

 

Ans:

 

0x100042 | 0x2 = 0x100042

8 4 8

The first row of output is the result of | operation.

 

0001 0000 0000 0000 0100 0010   | with

0000 0000 0000 0000 0000 0010   gives

0001 0000 0000 0000 0100 0010

 

Second row of output prints size of operand1, operand2, and operand1|operand2. operand1 is a long, operand2 is an int – result of | between a long and an int is a long. Hence we see sizeof long, int, and long printed in second row.

 

 

12. What is the result of following operations

1. 0x3B ^ 0xF0

0x3B 0 0 1 1 1 0 1 1
0xF0 1 1 1 1 0 0 0 0
^ 1 1 0 0 1 0 1 1

Answer: 0xCB

 

2. 0xFF ^ 0x01

0xFF 1 1 1 1 1 1 1 1
0x01 0 0 0 0 0 0 0 1
^ 1 1 1 1 1 1 1 0

Answer: 0xFE

 

3. 0xFF ^ 0x00

0xFF 1 1 1 1 1 1 1 1
0x00 0 0 0 0 0 0 0 0
^ 1 1 1 1 1 1 1 1

Answer: 0xFF

 

4. 0X87 ^ 0x78

0x87 1 0 0 0 0 1 1 1
0x78 0 1 1 1 1 0 0 0
^ 1 1 1 1 1 1 1 1

Answer: 0xFF

 

 

13. What is the result of following operations

1. ~0x3B

0x3B 0 0 1 1 1 0 1 1
~ 1 1 0 0 0 1 0 0

Answer: 0xC4

 

2. ~0xFF

0xFF 1 1 1 1 1 1 1 1
~ 0 0 0 0 0 0 0 0

Answer: 0x00

 

3. ~0x00

0x00 0 0 0 0 0 0 0 0
~ 1 1 1 1 1 1 1 1

Answer: 0xFF

 

4. ~0X87

0x87 1 0 0 0 0 1 1 1
~ 0 1 1 1 1 0 0 0

Answer: 0x78

 

 

14. What will be the output of following program

#include <stdio.h>
int main(int argc, char * argv[]) {
    unsigned char result = 0;
    unsigned char operand1 = 1;
    result=operand1<<3;
    printf("%x\n", result);
    return 0;
}

 

Ans: 8

The value of the integer is set to 1, which is 0x1

0x1 0 0 0 0 0 0 0 1
0x1 << 2 0 0 0 0 1 0 0 0

The program output will simply be “8”

 

 

15. What will be the result of following statements, assume signed char data type is used for storing all operands:

1. 0x4 << 1

0x4 0 0 0 0 0 1 0 0
<< 1 0 0 0 0 1 0 0 0

Answer: 0x8

 

2. 0x-1 << 1

-0x01 X 0 0 0 0 0 0 1
<< 1 X 0 0 0 0 0 1 0

Answer: -0x02

 

3. 0xA << 1

0xA 0 0 0 0 1 0 1 0
<< 1 0 0 0 1 0 1 0 0

Answer: 0x14

 

 

16. What will be the result of following statements, assume unsigned char data type is used for storing all operands.

1. 0x4 >> 2

0x4 0 0 0 0 0 1 0 0
>> 2 0 0 0 0 0 0 0 1

Answer: 0x1

 

2. 0x1 >> 1

0x1 0 0 0 0 0 0 0 1
>> 1 0 0 0 0 0 0 0 0

Answer: 0x0

 

3. 0xA >> 1

0xA 0 0 0 0 1 0 1 0
>> 2 0 0 0 0 0 1 0 1

Answer: 0x5

 

 

17. Write a program to determine behaviour of right shift on negative numbers for your system. Such a program would start with a negative integer and observe the value after successive right shift operations.

Ans: Depending on your system, this program may run into an infinite loop but it would still help you understand inner representation and behavior of right shift. Refer to bit level details in the book and twos complement article for details on inner representation.

#include <stdio.h>

int main (int argc, char * argv[]) {
    int num = -1;
    printf("%x\n", num);
    while(num) {
        num >>= 1;
        printf("%x\n", num);
    }
    return 0;
}

 

 

18. Write a code snippet to clear out ip flag in the above example. Plug it into a program and validate your code.

Ans:

flags = flags & (~(0x01 << ip_flag));

 

 

19. Determine endianness of your system.

Ans: Simply run the endianess program in the book and observe results on your system.

 

20. Modify the above example for determining endianness by using value 0x12345678 instead of 0x1.

Ans:

#include <stdio.h>

int main (int argc, char *argv[]) {
    int i = 0x12345678;
    char * ptr = &i;

    if (0x78 == *ptr) {
        printf("Little Endian\n");
    } else {
        printf("Big Endian\n");
    }
}

 

 

21. Write a program to check if an integer is power of two.

#include <stdio.h>

int main () {
    int num;

    // Prompt user to enter a number
    printf("Enter a number: ");
    scanf("%d", &num);

    // a number which is a power of two will
    // have ONLY one bit set in the integer
    // To find out using the bitwise operator
    // AND it with its n - 1
    // a n-1 of a number which is a power
    // of two will have all the following
    // bits toggled. Like
    // 8 = 1000, 8-1 = 7 will be 0111
    // 16 = 0001 0000, 15 will be 0000 1111
    // & on n and n-1 for a number that is power of
    // two will result in 0.
    if ( (num != 0) && ((num & (num - 1)) == 0) ) {
        printf("The number %d is a power of two", num);
    } else {
        printf("The number %d is not a power of two", num);
    }
    return 0;
}

 

 

22. Write a program that checks if an integer is negative by checking its MSB.

#include <stdio.h>

int main (int argc, char *argv[]) {
    int num = 0;

    printf("Enter a number: ");
    scanf("%d", &num);

    if (num & (1<<(sizeof(int)*8-1))) {
        printf("Negative number\n");
    } else {
        printf("Positive number\n");
    }
}

 

 

23. Write a program to count total number of set bits in an integer. A set bit has value 1.


#include <stdio.h>

int main () {
    int i, count = 0;

    // Prompt user to enter a number
    printf("Enter a number: ");
    scanf("%d", &i);

    while (i) {
        if( (i & 1) == 1) // is the first bit set, then {
            count++;   // increment count.
        }

        i = i >> 1; // Shift right, if no bits left i will be 0
    }
    printf("Number of bits set  are %d\n", count);
    return 0;
}