Objects First |
typedef struct classx *Classx;
A pointer's value is the address in the machine's memory
of the object that the pointer is pointing at.
We can declare pointers to any type of object by adding a
* before the name of each variable in a
declaration.
Note that in the definition:
int *x, y;
x is a pointer to an
int,
but y is an int.
If we want both to be pointers, we must write:
int *x, *y;
Some programmers will adopt a programming style rule which
says that puts only pointers or only objects in any one declaration.
However, if you're defining a list of objects and variables that are
going to be pointers to each object, then an alternating declaration
may be the best thing:
int x, *xp, y, *yp, z, *zp;
where xp, yp and
zp
are intended to be used as pointers to
x, y and z.
We can define a pointer to any C object:
int, char, double, struct, ...
and even to another pointer!:
int *ip, *jp;
char *s;
double *dp;
struct xy *xyp;
int **ipp;
The last is a pointer to a pointer which points to an int!
(More on pointers to pointers later.)
int *ip, *jp;
*ip = 1; /* Store 1 in the location
to which ip points */
x = (*ip) + (*jp); /* Add the values in the locations
pointed to by ip and jp */
In general, if we define:
some_type *ap;then we can use the dereferenced pointer, *ap, anywhere that we could use an object of the some_type class.
int *ip; ip = (int *)malloc( sizeof(int) ); /* initialise ip */ *ip = some_integer_function( 1, 2 ); x = (*ip) * (*ip); y = some_integer_function( *ip, 3 );Needless to say, the form in the previous paragraph - with parentheses - is safer and should be preferred because it leaves no possibility for a reader to be confused as to the intended behaviour of the code in which it appears.
x = *ip * *ip;
char *cp; cp = "Some very long and involved string";
int x, *xp; xp = &x;&x is the address of x and thus can be used to initialise an int *. & can be used both in an assignment statement and in the initialisation of a pointer variable:
double x; double *xp = &x; int p; int *pp = &p;
#include <stdlib.h> void *malloc( int n ); void *calloc( int n, int size );Note that these functions return pointers to void's. This means that the pointer they return can be assigned to any pointer without generating a type error. malloc allocates n bytes of space and returns a pointer to the allocated space. calloc allocates n*size bytes, clears them to 0 and returns a pointer to the allocated, zeroed space. (Read calloc as clear and allocate - or more precisely, clear after allocation.) calloc was designed to be used for arrays: one parameter is the number of elements and the other is the size of each element, but we can always call malloc( n*size ) if we don't need the space to be cleared.
Because pointers are addresses, all pointers have the same format and use the same amount of space (4 bytes on a typical 32-bit machine, 8 bytes on DEC's Alpha and other 64-bit machines). Thus all pointers are equivalent as far as the machine is concerned. However, once we've allocated space for an object with malloc or calloc, it's beneficial to keep them logically independent and class them by the type of object that they address. A good compiler will warn you if you try to assign a pointer to an object of type A to a pointer to an object of type B.
calloc's general behaviour is the same as that of malloc, so we will omit explicit mention of it from now on. However wherever malloc may be used, calloc may also be used with the same effect - except that malloc doesn't alter the current contents of the allocated space - it may be garbage left in memory by the last program! - whereas calloc clears it.
malloc requests memory for your program from an area of memory allocated by the linker and the operating system for dynamic memory allocation requests. This area is usually called the heap. Initially, it's just a "heap" of memory which has no allocated purpose - until malloc requests some of it.
| Don't forget to initialise pointers! |
Use either
|
void unpack( Date d, int *year, int *month, int *day );Since the parameters year, month and day are now pointers, they pass the address of a variable to the method. The method can now write a value into that address where it will be seen by the calling program.
#include "Date.h" /* Import the class specification,
now includding the unpack method */
void f( Date d ) {
int day, mon, year;
unpack( d, &day, &mon, &year );
printf("The date is %d:%d:%d\n", day, mon, 1900+year );
/* Candidate for Year 2000 bug ;-) */
Normally the variables in the invoking program are hidden from
the invoked function and copies of their values are passed to the
function.
Note that in this case, we passed the address of
day, month
and year. This allows the
unpack method to write
answers in the memory locations which the function f is using.
The implementation of unpack will look like:
void unpack( Date d, int *day, int *mon, int *year ) {
*day = d->day;
*mon = d->month;
*year = d->year;
}
unpack could also return a further value as the value of the
function itself (eg it could return TRUE if
d was a
legal date and FALSE otherwise,
or it could use the return value to flag that
d was
a candidate for the "2000 bug"!
Key terms |
|
Continue on to Input and Output Functions See also Advanced C programming: Pointer arithmetic Back to the Table of Contents |