CS 11 C track: lecture 4
n   Last week: arrays
 n   This week:
      n   Recursion
      n   Introduction to pointers
Lab 4
n   Harder than previous labs
n   One non-obvious trick
     n   hints on web page
     n   email me if get stuck
n   Support code supplied for you
n   Read carefully!
        Recursion (1)
n   Should be familiar from CS 1
n   Recursive functions call themselves
n   Useful for problems that can be decomposed
     in terms of smaller versions of themselves
    Recursion (2)
int factorial(int n) {
    assert(n >= 0);
    if (n == 0) {
        return 1;     /* Base case. */
    } else {
        /* Recursive step: */
        return n * factorial(n - 1);
    }
}
  Recursion (3)
factorial(5)
--> 5 * factorial(4)
--> 5 * 4 * factorial(3)
--> 5 * 4 * 3 * factorial(2)
--> 5 * 4 * 3 * 2 * factorial(1)
--> 5 * 4 * 3 * 2 * 1 * factorial(0)
--> 5 * 4 * 3 * 2 * 1 * 1
--> 120
          Pointers (1)
n   Address:
     n   A location in memory where data can be stored
     n   e.g. a variable or an array
     n   Address of variable x is written &x
n   Pointer:
     n   A variable which holds an address
     Pointers (2)
name     address            contents
 i      0x123aa8              10
 j      0x123aab           0x123aa8
 int i = 10;
 int *j = &i;      /* j "points" to i */
  Pointers (3)
int   i = 10;
int *j = &i;
printf("i = %d\n", i);
printf("j = %x\n", j);
printf("j points to: %d\n", *j);
           Pointers (4)
n   &i is the address of variable i
n   *j is the contents of the address stored in
     pointer variable j
     n   i.e. what j points to
n   * operator dereferences the pointer j
           Pointers (5)
n   The many meanings of the * operator:
     n   Multiplication
           a =    b * c;
     n   Declaring a pointer variable
           int *a;
     n   Dereferencing a pointer
           printf("%d", *a);
        Pointer pitfalls (1)
n   Declaring multiple pointer variables:
int *a, *b;        /* a, b are ptrs to int */
n   If you do this:
int *a, b;         /* b is just an int */
n   Then only the first variable will be a pointer
n   Rule: every pointer variable in declaration
     must be preceded by a *
        Pointer pitfalls (2)
n   Note that
int *j = &i;
n   really means
int *j; /* j is a pointer to int */
j = &i; /* assign i's addr to j */
n   Don't confuse this *j with a dereference!
       Pointers (6)
n   A harder problem:
int   i = 10;
int *j = &i;
int **k = &j;
printf("%x\t%d\n", &i, i);
printf("%x\t%x\t%d\n", &j, j, *j);
printf("%x\t%x\t%x\t%d\n",
       &k, k, *k, **k);
     Pointers (7)
name     address    contents
 i      0x123aa8      10
 j      0x123aab    0x123aa8
 k      0x123ab0    0x123aab
    Assigning to pointers (1)
int i = 10;
int *j = &i;
int *k;
/* Assign to what j points to: */
*j = 20; /* Now i is 20. */
/* Assign j to k: */
k = j;    /* Now k points to i too. */
/* Assign to what j points to: */
*j = *k + i; /* Now i is 40. */
           Assigning to pointers (2)
n   When pointer variable is on left-hand side of an
     assignment statement, what happens depends on
     whether it's dereferenced or not
     n   no dereference: assign the value on RHS (an address) to
          the pointer variable on the LHS
j = k;
     n   dereference: assign value on RHS into location
          corresponding to where pointer points to
*j = *k + 10;
     Assigning to pointers (3)
n When pointer variable is declared and assigned to
   on the same line:
int *j = k;
n it means:
int *j; /* declare j              */
j = k;        /* assign to j */
n i.e. assign the value on RHS (an address) to the
   pointer variable on the LHS
     Mnemonics: fetch/store
n When you use the * (dereference) operator in an
   expression, you fetch the contents at that address
printf("j's contents are: %d\n", *j);
n When you use the * (dereference) operator on the
   left-hand side of the = sign in an assignment
   statement, you store into that address
*j = 42;        /* store 42 into address */
           Pointers – call by reference (1)
n   Can use pointers for a non-obvious trick
n   Recall: in C, variables are copied before
     being sent to a function
     n   referred to as "call-by-value"
n   Significance is that passing a variable to a
     function cannot change the variable's value
n   But sometimes we want to change the
     variable's value when function returns
    Pointers – call by reference (2)
void incr(int i) {
    i++;
}
/* ... later ... */
int j = 10;
incr(j); /* want to increment j */
/* What is j now? */
/* Still 10 – incr() does nothing. */
    Pointers – call by reference (3)
void incr(int *i) {
    (*i)++;
}
/* ... later ... */
int j = 10;
incr(&j);
/* What is j now? */
/* Yep, it's 11. */
     Pointers – call by reference (4)
int j = 10;
incr(&j);
n You should be able to work out why this
   works
n Where have we seen this before?
  int i;
  scanf("%d", &i); /* read in i */
     Pointers – call by reference (5)
n Easy mistake to make:
void incr(int *i) {
      *i++; /* Won't work! */
      /* Parsed as: *(i++); */
}
n Need to say (*i)++ here
n Precedence rules again; use parens () if any
   confusion can exist
Next week
n   Pointers and arrays
     (the untold story)
n   Dynamic memory allocation