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.