CSC 161 Grinnell College Spring, 2015
 
Imperative Problem Solving and Data Structures
 
 

Laboratory Exercise: Types and Variables

Goals

The purpose of this lab is to explore types and variables in C.

Class Preparation before Class

Introduction

In Scheme, a variable (or identifier or parameter) can represent any type of data, and the type of a variable may change from one call of a procedure to another. For example, consider the following Scheme procedure that adds all numbers on a list or its sublists:

   (define sum-numbers
      (lambda (ls)
          (cond ((number? ls) ls)
                ((not (list? ls))  0)
                ((null? ls) 0)
                (else (+ (sum-numbers (car ls)) 
                         (sum-numbers (cdr ls))))
          )
      )
   )
  

When sum-numbers is called:

    (sum-numbers '((1) 2.0 four ((3/4) (five) 6)))
  

the parameter ls starts as a list, but various calls will give ls various values, including sublists, integers (e.g., 1, 6), real numbers (2.0), fractions (3/4), and symbols (e.g., four, five). At the end of this example, sum-numbers returns 9.75.

In C, the data type of each variable must be declared before the variable is used in a program (or procedure). Once declared, the data type cannot change within the procedure; values can change, but not the type of data.

When you start programming in C, you need to be familiar with the few primitive types of variables provided to manage data with. Often processing proceeds according to the type of data involved. However, in some processing situations, C allows for implicit and explicit type conversions between these storage classes. In this lab you will perform different operations, and examine the results.

Primitive Types

In C there are 4 primitive types:

   char     /* a character */
   int      /* an integer  */
   float    /* a real number (single-precision)*/
   double   /* a real number that needs twice the space as a float (double-precision) */

The following notes provide some background about each of these data types,

As we shall discuss in several weeks, these types of data are represented in different ways within a computer.

Work Started in Class

Computations with ints and doubles

C provides common arithmetic operations for both ints and doubles, with an extra capability for for ints.

Basic rules:

  1. Include the following code segment in a C program, compile the program, and observe the results:

      int a = 5;
      int b = 6;
      int c = a/b;
      int d = b/a;
      int e = (a + b) / 10;
      int f = (a + b) % 10;
      double x = (a + b) / 10;
      double y = (a + b) / 10.0;
      printf ("a=%d, b=%d, c=%d, d=%d, e=%d, f=%d, x=%lf, y=%lf\n", a, b, c, d, e, f, x, y);
    
    1. Review what is printed and explain each result.
    2. What happens if one changes the computation for variables f and y to (a + b) % 10.0; ? Explain why the compiler produces this result.

Observation: You may recall there is a fourth type, float, that was not involved in Step 1. doubles are often preferred to floats, because a double is stored more accurately than a float. Also, constants, such as 3.14 are almost always stored as doubles in C. An exception arises when memory is scarce, and one wants to use as little space as possible within a computer's memory. With the size of main memory in today's computer, however, size often is not a consideration, and doubles typically are used rather than floats.

We will discuss details of the various data types, including both doubles and floats, in a few weeks.

Assignment and Casting

In Step 1, the computations a/b and b/a were performed with ints. That is, the result was an integer, and any fraction of an integer was discarded. Also, in the case of computing y, the presence of the double 10.0 caused the machine to convert (a + b) to double and then perform division. In this case, the implicit type 10.0 caused conversion to double before the computation took place.

In C, we can assign values implicitly to int and double variables, but we also can explicitly ask the computer to change the data type before an operation. This explicit specification of a change in type is called casting

  1. Include the following code segment in a C program, compile the program, and observe the results:

      int k = 5.0;
      int m = 7.7;
      double n = 5;
      int p = k/m;
      double q = k/m;
      printf ("k = %d, m=%d, n=%lf, p=%d, q=%lf\n", k, m, n, p, q);
      double r = (double) (k/m);
      double s = (double) k / m;
      double t = k / (double) m;
      double u = (double) k / (double) m;
      printf ("r=%lf, s=%lf, t=%lf, u=%lf\n", r, s, t, u);
    
    1. Review what is printed.
    2. For each result printed, explain whether the division is done with ints or doubles and which, if any, numbers are converted to doubles when.

Observation: Sometimes there can be a danger in casting. Types have sizes. If you try to put a number that is bigger than the size of the type you are casting it to, you may get undesired results.

Operator Precedence

After deciding what operator you will use, you need to put them in certain order or in parentheses because the program will be read in a certain order and so the operators will be applied in a certain order.

  1. Copy this code in a program. What do you think the result will be? Test this out by printing the value.
        	int v;
    	v = 5 + 4 * 3 + 1
    
  2. Copy this code in the same program. Think about your expected result and then see what the program prints.
    	int w;
    	w = (5 + 4) * (3 + 1)
    	
    

Incrementing and Decrementing Numbers

Suppose you have a counter days that counts down the number of days you have left for the summer. Every day that passes, you need to decrement the number of days to get your countdown going. You could do it like this:

	days = days - 1;

This would mean that your are taking the number of days, subtracting 1 from it, and setting that as my new days value.

There is a shortcut to saying that the new value of days is the old value of days -1. Here it is:

	days -= 1

You can do a variety of operations just like this:

In practice, 1 is the most common value to add or subtract from a variable, and C provides two special ways to increment by 1. For a variable a,

  1. Examine the output of the following code, in which variables are incremented as the only part of an expression.

       int a = 1;
       int b = 7;
       printf ("a = %d, b = %d\n", a, b);
       a++;
       ++b;
       printf ("a = %d, b = %d\n", a, b);
    

    In this code the ++ operation is the only part of the statement. Note what results are obtained.

  2. Now consider the following example that combines the increment operators with other activities (e.g., assignment)

      int a,b,c;
      a = 0;
      b = a++;
      c = ++a;
      printf(" a = %d b = %d c = %d\n", a,b,c);
      a = 0;
      b = ++a;
      c = a++;
      printf(" a = %d b = %d c = %d\n", a,b,c);	
    

    Examine the output and explain the result. For example, explain any difference observed between the two increment operators in this context.

  3. The next block combines the increment operators within a print and within arithmetic expressions. Examine the output to determine whether or not there is a difference between the two increment operators in this context.

      int r, s;
      r = 5;
      s = 7;
      printf(" r = %d s = %d\n", ++r, s++);
      printf(" r = %d s = %d\n", r, s);	
      int t = r++ + s++;
      printf(" r = %d s = %d, t = %d\n", r, s, t);	
      int u = ++r + ++s;
      printf(" r = %d s = %d, u = %d\n", r, s, u);	
    
    
  4. In addition to the increment operators, ++a and a++, C provides pre- and post-decrement, --a and a--, that subtract one from the variable.

    Repeat Step 7, replacing ++ by -- throughout. Again, examine the output and explain what is printed.

Conclusion: When combined with other operations, the increment operations ++a (pre-increment) and a++ (post-increment) cause different values to be used in processing. This observation yields the following programming observation and suggestion:

Homework

Characters

In C, a character is stored as in a coded form — an integer between 0 and 255. (Historically, the code used numbers 0 to 127, but the extended code now uses codes over the full range 0 to 255.) Thus, a char is considered to be an integer with a restricted size. For the most part, we do not care what the internal code is for an integer — conceptually, we just have a character. Technically, the underlying code is called the American Standard Code for Information Interchange or ASCII.

  1. The program ascii-print.c prints many of the ASCII values along with their corresponding characters. Codes smaller than 32 correspond to characters that are not printable (e.g., a backspace, tab, line feed, return, etc.). Similarly, codes larger than 126 may not print properly in terminal windows (e.g., code 177 is ±, code 181 is µ, and code 216 is Ø). Since only codes between 32 and 126 (inclusive) reliably print in a terminal window, the program uses a for loop that starts with code 32, the code for a space character, and ends at 126.

    1. What is the corresponding character to the ASCII value 85?
    2. What is the ASCII value for the character 'A'?
    3. What is the ASCII value for the character 'a'?
    4. What is the integer difference between the values of 'A' and 'a' ?
    5. What relationship can you observed for the codes for 'a', 'b', 'c', 'd', and the other lower case letters?
    6. What relationship can you observed for the codes for '0', '1', '2', '3', and the other digit characters?
    7. What relationship can you observed for the codes for 'A', 'B', 'C', 'D', and the other upper case letters?
    8. What code is used for the character 0? (Note that the code for char 0 is not zero!)

Adding ints to chars

Since characters are stored according to their integer codes, it is possible to add an integer value to a char value.

  1. Include the following lines of code within a program:

      char ch = 'a';
      ch = ch + 7;
      printf("ch + 7  = '%c'\n", ch);
    
    1. Save, compile, and run the program again.
    2. What is the value of ch?
  2. Add 7 to ch again (you can just copy the last two lines again) and a print out the value.

    1. What is printed?
    2. Is th at what you expected?
  3. In C, a char is considered a type of small int, so it is possible to assign a char variable an integer value. Set ch to 48 and print out the result:

      ch = 48;
      printf("char ch = '%c'\n", ch);
    

    Note what is printed. Can you explain why?

  4. Set ch equal to the integer 0 and print it again.

    You may notice the print statement doesn't print out ch as being zero; rather the two single quotes are printed next to each other. The reason is that the character code for the integer 0 is called a "NULL"; when printed the cursor does not move in any way — effectively printing of the character for code 0 is ignored in the output.

Feedback Welcome

Development of laboratory exercises is an iterative process. Prof. Walker welcomes your feedback! Feel free to talk to him during class or stop by his office.