CS61C Fall 2014 Lab 02 - C

Goals

Setup

We recommend you create a new directory for each assignment. For example, to create a directory named lab02 in your home directory, type:

$ mkdir ~/lab02

Afterwards, copy the contents of ~cs61c/labs/02 to the directory.

$ cp -r ~cs61c/labs/02/* ~/lab02

Compiling and Running a C Program

In this lab, we will be using the command line program gcc to compile programs in C. The simplest way to run gcc is as follows.

$ gcc program.c

This compiles program.c into an executable file named a.out. This file can be run with the following command.

$ ./a.out

gcc has various command line options which you are encouraged to explore. In this lab, however, we will only be using -o, which is used to specify the name of the executable file that gcc creates. Using -o, you would use the following commands to compile program.c into a program named program, and then run it.

$ gcc -o program program.c
$ ./program

Exercise 1: Simple C Program

In this exercise, we will see an example of preprocessor macro definitions. Macros can be a messy topic, but in general the way they work is that before a C file is compiled, all macro constant names are replaced exactly with the value they refer to.

In the scope of this exercise, we will be using macro definitions exclusively as global constants. Here we define CONSTANT_NAME to refer to literal_value (an integer literal). Note that there is only a space separating name from value.

#define CONSTANT_NAME literal_value

Now, look at the code contained in eccentric.c. We see four different examples of basic C control flow. First compile and run the program to see what it does. Play around with the constant values of the four macro: V0 through V3. See how changing them changes the program output. Modifying only these four values, make the program produce the following output.

$ gcc -o eccentric eccentric.c
$ ./eccentric
Berkeley eccentrics:
====================
Happy Happy Happy
Yoshua

Go BEARS!

There are actually several different combinations of values that can give this output. You should consider what is the minimum number of different values V0 through V3 can have to give this same output. The maximum is four, when they are all distinct from each other.

Checkoff [1/3]

Exercise 2: Bit Operations

For this exercise, you will complete bit_ops.c by implementing the following three bit manipulation functions. You will want to use bitwise operations such as and (&), or (|), xor (^), not (~), left shifts (<<), and right shifts (>>). Avoid using any loops or conditional statements.

// Return the nth bit of x.
// Assume 0 <= n <= 31
unsigned get_bit(unsigned x,
                 unsigned n);
                 
// Set the nth bit of the value of x to v.
// Assume 0 <= n <= 31, and v is 0 or 1
void set_bit(unsigned * x,
             unsigned n,
             unsigned v);
             
// Flip the nth bit of the value of x.
// Assume 0 <= n <= 31
void flip_bit(unsigned * x,
              unsigned n);

Once you complete these functions, you can compile and run your code using the following commands.

$ gcc -o bit_ops bit_ops.c
$ ./bit_ops

This will print out the result of a few limited tests.

Checkoff [2/3]

Exercise 3: Bit Analysis

For this exercise, you will complete bit_count.c by defining and implementing a function that analyzes the bits in a given integer. You must define a function that given some unsigned integer input x, computes the following:

We are assuming 32-bit integers, so valid positions range from 0 to 31. If all bits are 0, both bit positions are -1 to indicate that there are no 1 bits.

During your implementation, you are not allowed to use structs.

Once you have declared and implemented this function, you can compile and run your code using the following commands. The program takes in a single input, which is parsed as the number to be analyzed.

$ gcc -o bit_count bit_count.c
$ ./bit_count 0x801
   NUMBER: 2049
     BITS: 2
HIGHEST 1: 11
 LOWEST 1: 0

You should test your program on various inputs.

Checkoff [3/3]