More C for Java Programmers




CS152

Chris Pollett

Sep 8, 2021

Outline

Introduction

Where we were in our C Intro

Program structure

Generally, for each module (say .c file) of your program, you put all its function prototypes, struct definitions, #define's, global variable declarations, etc. into a header file (a .h file) for that program and then include it with the line like:

#include "foo.h" /* double quotes unlike <foo.h>, also searches current directory */

Since, you might use the same header file for several modules, the header file might have at its start some preprocessor code like:

#ifndef FOO_H
#define FOO_H
//header file code
#endif // this prevents the header from being included more than once.

Pointers

Roughly, pointers allow us to refer to a memory address.

Example:

 
   int a, *b; /* b is declared as a pointer to an int memory address, 
        (what * means when declaring a variable) */
   a = 5;
   b = &a; /* now b points at where a is stored in memory 
       (what & on a non-pointer means) */
   printf("%d", *b); //prints 5.
   *b = 6; /* this changes the value of what's stored at the address b points to */
   printf("%d", a); // prints 6.

More Pointers

In-Class Exercise

Struct's

C has a mechanism for collecting together a bunch of existing data types into a new one using struct's. These can be thought of as classes without member functions.

struct Person
{
     char name[12];
     int age;
}; //notice the ;
struct Person p, *ptr;
strcpy(p.name, "Bob"); //in string.h. Note p.name[3] = '\0' after
// many useful string functions like strlen, strcmp, etc are in string.h
p.age = 5;
ptr = &p;
printf("%d %s %s", p.age, (*ptr).name, ptr->name);

More on struct's

You can also declare:

struct
{
   int a,b;
} test;
test.a = 5; /* so have declared a variable test but have not given the kind of struct it is a name */

The syntax struct Person p; of the last slide is sometimes awkward. To simplify it you can write:

typedef struct Person person_type;
person_type a,b,c;

Using structs and pointers you can create recursive data structures:

struct mylist
{
   int a;
   struct mylist *next, *prev;
} test;

Remark: You can fake classes by using struct's which have function pointers as members.

Union's and Enum's

Memory Allocation

File I/O

Example Reading From a File in C

#include <stdio.h>
int main(int argc, char * argv[]) //notice getting command-line args
{
   int c;
   FILE *fp;
   if(argc < 2)
   {
       return 1; //bail if no file specified

   }
   fp = fopen(argv[1], "r"); // r is for reading, w for write, rb for binary, etc
   while ((c = fgetc(fp)) != EOF) 
   {
       printf("%c", (char)c );
   }
   fclose(fp);
   return 0;
}

Buffering

make

Makefile Structure

A Makefile consists of rules of the form:

target1: depends_on1 depends_on2 ...
<tab>command1
<tab>command2
...
<blankline>
target2: depends_on1 depends_on2 ... #etc
# is used for a single-line comment

Notice the use of tabs is important!

Some example targets

myprog: myprog.o
	cc -o $@ $<
 
myprog.o: myprog.c
	cc -c -o $@ $<
# $@ refers to the target $< refers to the first dependency
clean:
	rm -f myprog myprog.o

More on Makefiles

You can declare variables in a Makefile using the format varname = value like:

   CC = gcc
   SUBDIRS = io linkedlist

These variables could then be used:

all : $(SUBDIRS)
   $(CC) historylesson.c -o historylesson

An example of a multi-line make rule might be something like:

io :
   @echo "Making io..."
   cd io
   make all