Lots of students were prevented from coming to class by
our snowstorm. I hope that these notes help you a little
bit. Also check with other students who did make it to
class and took notes.
Karen
Allowed Operations on Pointers
int *px, *py; int x, y; px = &x; /* get address */ py = &y; px = py; /* assignment */ /* both lhs and rhs are same type */ px = NULL; /* assignment to NULL */ if ( px == NULL) /* comparison */ printf("pointer is NULL\n");
NOT Allowed on Pointers
int *px, *py, *pz; px = 12; /* assignment to non-NULL literal */ pz = px + py; /* add or subtract of */ /* two pointer values */ px = py * 2; /* multiply or divide of */ /* pointer value(s) */
Draw a Diagram:
int x, y, z; int *px, *py, *pz; px = &x; py = &y; pz = &z; *px = 24; py = px; z = 25; *py = x - z;
(Karen's start to a diagram) --- --- x | | | | px --- --- --- --- y | | | | py --- --- --- --- z | | | | pz --- ---
Arrays
. | . | |--------| / | | base / |--------| | | | base + (1 * size) | |--------| array | | | base + (2 * size) (one | |--------| element | | | base + (3 * size) per | |--------| box) | . | ..
0 1 2 3 4 (index) --------------------- | | | | | | | | | | | | ---------------------
How this array is filled in in later class examples.
0 1 2 3 4 (index) --------------------- | 1 | 2 | 3 | 4 | 5 | ---------------------
Declare:
int a[5];
Use:
a[0] = 1; a[1] = 2;
As allocated within memory:
(one integer fits into a box)
. | . | |--------| / | | a / |--------| | | | | |--------| | | | | |--------| | | | \ |--------| \ | | |--------| | . | .
Again, what memory (this array) looks like when filled in.
. | . | |--------| / | 1 | a / |--------| | | 2 | | |--------| | | 3 | | |--------| | | 4 | \ |--------| \ | 5 | |--------| | . | .
C uses pointer notation with arrays:
a[i]
is equivalent to *(a + i)
and
&(a + i)
is equivalent to a + i
int a[5]; int *ap; ap = a; ap++; /* ap has the address of a[1] */ *ap = 2; ap++; /* OK. */ a++; /* BAD! NOT ALLOWED! */ /* a is a label, not a pointer! */
#include <stdio.h> # define MAXARRAYSIZE 5 main() { int intarray[MAXARRAYSIZE]; int *iap; /* a pointer to an int */ int k; /* loop induction variable */ /* one implementation */ /* notice the use of pointers and pointer arithmetic! */ iap = intarray; for ( k = 0; k < MAXARRAYSIZE; k++) { *iap = k + 1; iap++; } iap = intarray; for ( k = 0; k < MAXARRAYSIZE; k++) { printf("%d\n", *iap); iap++; } /* another implementation */ for ( k = 0; k < MAXARRAYSIZE; k++) { intarray[k] = k + 1; } for ( k = 0; k < MAXARRAYSIZE; k++) { printf("%d\n", intarray[k]); } }
From the lecture notes:
int a = 3; int b = 8; int c = 0; int *cp; c = a + b; cp = &c; cp++; /* allowed, but probably not reasonable */
Contrast this code with:
iap = intarray; for ( k = 0; k < MAX; k++) { . . iap++; /* correct and reasonable? */ }
C does not do any sort of
bounds checking!
int ar[12]; ar[12] = -1; /* No compiler error! */ ar[300] = ar[300] + 3; /* OK! */
This leads to the question:
Why no bounds checking?
#include <stdio.h> void increment (int a); main() { int x; x = 1; printf("before call, x = %d\n", x); increment( x); printf("after call, x = %d\n", x); } void increment(int a) { a++; }
Some explanation of this slide:
This program prints
before call, x = 1 before call, x = 1
The reason for this output is that C implements only call by value parameter passing.
If we wanted the increment function to increment x
,
then the main
program must pass a pointer to x
,
rather than a copy of x
.
Here's the code to do that, with underlines showing items
that changed in the code:
#include <stdio.h> void increment (int *a); main() { int x; x = 1; printf("before call, x = %d\n", x); increment(& x); printf("after call, x = %d\n", x); } void increment(int *a) { (*a)++; }
int main() { x = a(); } int a (){ y = b(); } int b (){ z = c(); } int c (){ }
main
calls a
a
calls b
b
calls c
c
returns to b
b
returns to a
a
returns to main
The call tree for this code:
main | \ / a | \ / b | \ / c