CSPP 51081 - Tutorial #8


Files for this tutorial: tut8.zip

Enumerations

We have already seen that we can declare constants using #define and the const qualifier.
We can also declare an enumeration, which is a type that can take a set of named integer values:

  enum color { RED, YELLOW, GREEN }
 
  enum color c1;

  ...

  c1 = GREEN;    /* same as c1= 2; */
 
  if (c1 != RED)

  ...

By default, values start at zero, so here RED has the value 0, YELLOW 1, and GREEN 2.
Explicit values may be specified. Here, JAN has value 0, FEB 2, etc. :


  enum months { JAN=1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC };
 

As with the struct keyword, we can use enum with typedef

  typedef enum __color { RED, YELLOW, GREEN } color
 
  color c1;

  ...

  c1 = GREEN;    /* same as c1= 2; */

We can compare enumeration values

 if(mon1 < DEC)
  ...

We cannot use the same enumeration constant with more than one enumeration.

Random numbers

We can use the rand function in stdlib.h to generate a pseudo-random integer, from zero and RAND_MAX.

  int rand(void);

By default rand is seeded with a value of 1.
We can call srand to set a new seed for a sequence or random intergers.

  int srand(unsigned int seed);

If we want to see a unique sequence of random numbers each time our program runs, then we can seed srand with a number that varies with the time of day, such as time in time.h.

  srand(time(NULL));

  ...

  int i = rand();

ex1_rand.c  Text

Function pointers

The memory allocated for a process includes space for compiled source code. The function name indicates the starting address of code that defines that function. We can use a function pointer to point to a function, i.e., to machine instruction.

Declaring and assigning a function pointer

When we declare a function pointer variable, we must indicate the return type and arguments of a function:

 char (* pStrFunc )(const char *);

  ...

  pStrFunc = &strdup;

This assignment (without &) is also valid:

 pStrFunc = strdup;

Purpose of function pointers

With function pointers, we can determine at runtime which function to call.

Function pointers can be: assigned, stored in arrays, and passed as arguments

You will never need to call malloc or free with a function pointer!

Example: sorting

First, lets look at an example of sorting a list of intergers, without using function pointers:

ex2_bubble_sort.c   Text

Now, let's compare this to another version that uses function poiters.
Here, we can decide at runtime how pointers are called:

ex3_func_ptr.c   Text

The qsort library function

We can also use the library function qsort in stdlib.h to sort an array of data.

  void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *));

qsort sorts the array with nmemb elements of size size. The base argument points to the start of the array.

What is the type of the third argument, compar?

  int(*compar)(const void *, const void *));

ex4_qsort.c   Text

Exercise: Modify Example 4 so that dates are sorted by month and date, not just month.

ex5_str.c   Text

SOLUTION:
ex5_str_soln.c   Text

Using typedef to define a function pointer type

Using typedef to define a function pointer type

We can also defien a function pointer type with typedef. Note the syntax is someone different than usual typedef declarations:

 typedef char (* pStrFunc_t )(const char *);   /* define the type pStrFunc_t */

 pStrFunc_t pStrFunc;

  ...

  pStrFunc = &strdup;