L-28 MCS 260 Wed 24 Oct 2001
Observe in the program below the very important difference between
- the declaration of a pointer: double *ptr_to_pi;
- assigning a value to the pointer: ptr_to_pi = π
- assigning a value to the variable the pointer points to:
*ptr_to_pi = 2.0l*asin(1.0l);
note that the statement double *ptr_to_pi = &pi
assigns to the pointer: the * belongs to
the declaration and should not be seen as a dereferencing.
/* L-28 MCS 260 Wed 24 Oct 2001 : addressing and dereferencing
Pointers allow to manipulate variables indirectly,
as show in the program below. Since we use asin of math.h,
this program should be compiled with the option -lm. */
#include<stdio.h>
#include<math.h>
int main(void)
{
double pi = 3.1415; /* very crude approximation */
/* double *ptr_to_pi = π */ /* pointer to pi */
double *ptr_to_pi; /* observe the difference : */
ptr_to_pi = π /* no dereferencing operator here !!! */
printf("pi = %.15lf\n", pi);
*ptr_to_pi = 2.0l*asin(1.0l); /* improve approximation of pi */
printf("pi = %.15lf\n", pi);
return 0;
}
The indirect manipulation of variables allows us to create
more powerful functions :
/* L-28 MCS 260 Wed 24 Oct 2001 : call by reference
The program below is another illustration of call by reference:
we create a function that sorts two integers in increasing order.
To bring the integers in increasing order, the function uses a
temporary variable in the swapping. */
void sort ( int *a, int *b );
/* on return, *a <= *b */
#include<stdio.h>
int main(void)
{
int a,b;
printf("Give two integers : ");
scanf("%d %d", &a, &b);
sort(&a,&b);
printf("The numbers in increasing order : ");
printf("%d %d\n", a, b);
return 0;
}
void sort ( int *a, int *b )
{
if (*a > *b)
{
int tmp = *b; /* tmp only needed to swap */
*b = *a;
*a = tmp;
}
}
The following program is a warm up for an application of
pointers to void :
/* L-28 MCS 260 Wed 24 Oct 2001 : functions that return pointers
Below we give an example of a function that returns a pointer. */
int *integer_divisor ( int n, int d );
/* returns a pointer to the integer quotient n/d */
#include<stdio.h>
int main(void)
{
int a,b;
int *quot;
printf("Give an integer : ");
scanf("%d", &a);
printf("Give a nonzero divisor : ");
scanf("%d", &b);
quot = integer_divisor(a,b);
printf("The integer quotient : %d\n", *quot);
return 0;
}
int *integer_divisor ( int n, int d )
{
int iq, *ptr_iq; /* iq is value, ptr_iq is pointer to iq */
iq = n/d;
ptr_iq = &iq;
return ptr_iq;
}
With pointers to void we can circumvent the typing mechanism of C.
/* L-28 MCS 260 Wed 24 Oct 2001 : pointers to void
To illustrate pointers to void, we create a routine that can return
variables of different types. */
void *generic_divisor ( int n, int d, int flag );
/* result is the integer quotient n/d, when flag = 0,
float quotient n/d, when flag = 1,
double quotient n/d, when flag = 2. */
#include<stdio.h>
int main(void)
{
int n,d;
int *iq;
float *fq;
double *dq;
printf("Give an integer : ");
scanf("%d", &n);
printf("Give a nonzero divisor : ");
scanf("%d", &d);
iq = (int *) generic_divisor(n,d,0); /* cast void* to int* */
printf("The integer quotient : %d\n", *iq);
fq = (float *) generic_divisor(n,d,1); /* cast void* to float* */
printf("The float quotient : %f\n", *fq);
dq = (double *) generic_divisor(n,d,2); /* cast void* to double* */
printf("The double quotient : %.15lf\n", *dq);
return 0;
}
void *generic_divisor ( int n, int d, int flag )
{
int iq, *ptr_iq; /* iq is value, ptr_iq is pointer to iq */
float fq, *ptr_fq;
double dq, *ptr_dq;
switch(flag)
{
case 0: iq = n/d;
ptr_iq = &iq;
return ptr_iq;
case 1: fq = ((float) n)/((float) d);
ptr_fq = &fq;
return ptr_fq;
case 2: dq = ((double) n)/((double) d);
ptr_dq = &dq;
return ptr_dq;
}
}