Lecture 7: More Pointers and Some Pointer Problems

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Exercises with Pointers

char *cp1, *cp2;
int *ip;

- *ip is an integer
- *cp is a character

- we can use *cp anywhere we could use a regular character.
- cp is a pointer to a character - we cannot use it where we would
  use a regular character - we can only assign addresses to it.

char c = 'a';
char *cp;

cp = &c;

printf("%c", *cp);

- more examples:

float a = 3.0, b = -17.0;
float *fp;

fp = &b;		/* fp points to b */
b++;			/* *fp is now -16.0 */
*fp = *fp - 2.0;	/* b is now -18.0 */
a = *fp;		/* a is now -18.0 */
a++;			/* a is now -17.0  but b and *fp are -18.0 still */

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The Great Danger of Pointers:

int p;

*p = 3;

- Oh, oh. The pointer p is uninitialized. A random address.  Anything
could be stored at that address ... nothing interesting, another part of
your program, your program code, someone else's program,
the operating system code!  
- we are writing all over it with the number 3!
- what does this mean?  Essentially anything can happen
to the program after this point.  Often, you will get one of
the following errors:

- "segmentation fault"   == you have accessed a "bad" memory location
			 == pointer error

- "bus error" == similar
	      == pointer error

- "system error #11" == similar

- similarly:

int a[3];
int b[3];

a[4] = -6;

- only 3 memory slots have been allocated for your program!  
- Perhaps b has been allocated 3 slots immediately after a's 3 slots ...
perhaps not ...

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Arrays and Pointers:

- an array name is just a pointer to a series of memory slots that
	have been allocated for you 

- one difference: array names are really *constant* pointers,
	you cannot assign to them

- array indexing:  add 3 to the address, then look at the value in the
	slot:

  a[3] == *(a + 3)

- thus:

void zero_array(int a[], int length);

void zero_array(int *a, int length);

are the same.  The first gives the reader of the program a hint that
a will be used as an array rather than a pointer.

- return arrays from functions as pointers:

int *zero_array(int *a, int length)
{
	int i;

	for (i=0; i< length; i++){
		a[i] = 0;
	}

	return a;
}

.
.
.

int a[4];
int *b;

b = zero_array(a);

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

			*** Watch Out ***

- what happens when you declare an array in a procedure and
then return it?

- Incorrect Example:

int *make_array(int length)
{
	int a[length];  /* error: "Illegal Constant Expression" */

	return a;
}

- Incorrect Example 2:

int *make_array(int length)
{
	int a[100];
	
	return a;
}

- in the second example, we have fixed the length of the array, 
but the return statement only returns the pointer to the array.

- it does not copy all of the values in the array.

- when the function returns, all local storage "disappears" - we
lose all of the values in the array but we copy the pointer.

- if we later dereference the pointer (use *), anything can happen ...

- next time we will discuss how to solve these problems.