CS61C Spring 1999

Section 23 TA: Gek Siong Low (cs61c-tb)

Week 1 Discussion notes

In view of the first project, I have written out this brief review of C and pointers. Note that I will not be discussing the syntax of C here, as that is well covered in the K&R text, which I strongly suggest that you get if you are not already pro ficient programming in C.

The purpose of the first project is to ensure that you pick up sufficient knowledge of C (or serve as a quick review if you already know C) required of the course. Basic concepts you must read up are file I/O, memory allocation, manipulate strings, typ ecasting. The code you need to write is actually pretty short.

This set of notes may be quite different from what I discussed in class, because it's my first time teaching and I don't know what to prepare. This amount of information contained here is not an indication of the length of my future notes, if any. ( The other TAs seem to have collected a lot of materials over the years, so I don't want to overload you guys with too much repeated information).

The C Language - An Overview

C is the de-facto language in industry, although Java is catching up fast. Java syntax is based on C, so it should be very easy for Java programmers to make the switch. However, Java has a lot of safety features and abstractions which is absent in C, w hich is what makes C so powerful yet frustrating to master. The culprit? Pointers. However, it is necessary that you understand pointers when leaning about the machine structures, that is why we do not use Java here. In this notes, I will mention several common traps to avoid when using pointers.

What Java has that C doesn't

1. Classes and all the good things (encapsulation, protection, etc) that come with it

2. Bounds-checking to keep your program safe and sound

3. Exceptions for file handling

4. No pointers to lead you astray

5. Garbage collection

What C has that Java doesn't

1. Global variables (although you probably can do it in Java with one all-encompassing Main class or something)

2. Structs, which can actually be used to "construct" classes, but you don't want to do that (unless you are in CS164)

3. Header files for project management (blessing or curse, depending on your experience with them)

4. Typecasting. Almost any type can be typecasted to some other type. Powerful but easily abused.

5. Pointers! They are all over the place.

6. You must allocate/free memory manually. You have ultimate control over how much memory you use, but it can get really difficult to manage them.

C++ is an OOP extension of C, but I don't think we'll be using them in this class.

Some differences between C and Java

1. Arrays are passed by value in Java but passed by reference in C. In other words, what is passed in C is the pointer to (or address of) the array, not the contents of the array.

2. There are no strings object in C. Strings are exactly the same as arrays of characters (bytes). So strings get passed around by reference too.

A short C example

/* Generates an n-times multiplication table */
#include <stdio.h>
int n=3;

int main() {
  int i;
  for (i=1; i<=10; i++) {
    printf("%d times %d is %d\n", i, n, i*n);
  };
  return 0;
};

As you can see, C is basically the same as Java. The #include line tells the C compiler to link in the stdio.h standard library, which contais the printf() function. The printf() function is probably one function you'll always use. It accepts a formatt ed string and variable number of arguments, depending on the format string. The %d means to substitute in the next argument and output it as an integer. Since we have 3 %d's we must have 3 arguments after the format string. Other format specifiers are %f (floating point), %e (floating point with exponent), %x (hexadecimal), %o (octal), %c (character), and %s (string).

Some commonly used libraries and functions

Library

Function

Purpose

stdio.h

printf

formatted output

 

scanf

formatted input (read your manual before using this one!)

string.h

strcmp

string comparison

 

strlen

length of string

 

strcat

append one string to another

 

strcpy

copy one string to another

 

 

 

Other functions

 

 

malloc

 

allocates memory

free

 

frees a block of memory

file I/O functions

 

there are many ways to this on the Unix platforms. Pick your favorite method.

A more complicated C example

#include <stdio.h>

struct foo {
  int *p;
  int x;
  char a[3];
  char *b;
};

char z='e';
int b[2]={8,9};

struct foo c={b, 10, {'a','b','c'},&z};
struct foo *d;
d=&c;

Structs allow you to group different data types in a record. This example illustrates structs and pointers. Here, the data type foo is declared as a struct with 4 elements:

1. a pointer to an integer p (32 bits=2 words=4 bytes in this class)

2. an integer x (4 bytes)

3. an array of 3 characters. The location of this array is within the structure, and takes up 4 bytes even though there are only 3 bytes due to word alignment (will be discussed later in the class)

4. a pointer to a character, so this is 4 bytes (not one, this is a pointer, not a character!)

Here are some examples of referencing the struct elements and their values:

Expression

Value

c.x

10

c.p

address of first element of b

c.a[1]

'b'

c.b

address of character z (&z)

*(c.b)

'e'

d->x

10

(*d).x

10

The last two examples are equivalent expressions. The '->' means to dereference d (*) and access the member x (.)

Incrementing pointers

When we write 'ptr++', where ptr is a pointer, how much is ptr incremented by?

The answer is not 'one byte', nor 'one word', but depends on the type of ptr. If ptr is declared to be 'char *ptr', then the increment is by one byte. If it is 'int *ptr', the increment is by one word (or 4 bytes). If it is 'struct foo *ptr', ptr++ inc reases ptr by whatever is the size of foo! Hence, ptr++ is NOT the same as ptr=ptr+1!

Strings

Strings in C are arrays of characters. You can declare them in two ways (applies to any array, not just strings):

1. Statically - char message[20]="Hello World!\n";

2. Dynamically - char *message;

For dynamic allocation, you have to manually use malloc and free to allocate/deallocate heap space for the string. However, since in the second example, message is just a pointer. you can use it to point it to any other string as well, which may be con fusing sometimes. The general rule is that when you allocate memory for a pointer type, you better free it before you start pointing it to somewhere else. You must also ensure that no other pointers are pointing to that same memory location, which may cau se segmentation faults or unpredictable behavior later.

C strings are null-terminated, meaning they end with a null character, so remember to include that null character when you declare or allocate memory for the string.

Common pitfalls when programing in C

Some of the mistakes are what I think should be common mistakes when programming in C, and some of which I often make. I hope by compiling them together in one spot will help you in debugging your program.

1. Using '=' instead of '==' in a decision statement (if, while, etc). Remember that the result of an assignment (=) is always true!

2. Using '==' instead of strcmp for string comparisons. Pascal programmers always make this mistake (I was one). Because strings are essentially arrays of char, using '==' means to compare their addresses, which are of course different for different st rings.

3. Going out of bounds when traversing an array with a pointer. Remember that C does not perform bounds checking for you!

4. Accessing a null pointer. This is the #1 most common cause of segmentation faults.

5. You have freed a block of memory but there are other pointers pointing to it. Anything may happen when you access those pointers later, from seg faults to unpredictable behavior.

6. Allocate memory but not freeing them. Actually, this is not a mistake, but what I myself consider to be unhealthy programming practice. If you cannot account for all memory you use, you may have a lot "lost memories" out there, which may or may not have an effect on your program. The OS will reclaim the memory upon exit, so it is not really necessary to free every block of memory when you exit, however I will do that just to be rigorous about it. Also, try to make it, "one malloc – one free". Freein g a block of memory as the result of a conditional statement is extremely dangerous. If you free it twice, your program will crash.

7. Returning a local (static) array. Remember that in C, what you return is actually a pointer to the local array, which is allocated on the stack (will be discussed in class later). When your function exits, the local array is officially not there any more, although you may still be able to access it (until you do call another function). The right thing to do here is to malloc a new array on the heap, copy the array over, and return the new array.

A note on how to use gcc and gmake

'gcc' is short for "GNU C Compiler", which is the standard compiler found on most Unix systems today. There is another compiler named 'cc' , which you probably shouldn't use for this class. 'gcc' is extremely powerful, with so many options that I don' t think there is anybody who knows all of them, but here are some basics on using it.

gcc -Wall -g -o output_filename source_file1 source_file2 ....

The -Wall option generate all warning messages (not error messages). Don't use it if you find it too irritating.

I forgot what -g means, but I see so many people using it so here it is. Check the man pages as an exercise. You probably should learn how to use man pages anyway.

The -o tells the compiler to output to a specific filename. Omitting this option (-o plus the filename) will output to the file a.out in the current directory.

For the first project you'll also be using 'gmake' (GNU make). A makefile is simply a collection of instructions that are grouped together which are executed when the appriorate arguments are supplied to gmake (it's actually much more than that). This is a very powerful for maintaining and compiling large projects. It will be useful to learn it for the upper-division classes, but for this class, you can simply follow the instructions given to you.

Written by: Gek Siong Low (cs61c-tb) Spring 1999