In previous sections we noted, more or less in passing, two important facts about arrays and pointers:
1.An array name is actually a pointer.
2.Array notation (subscripts) and pointer notation are interchangeable.
These ideas are significant enough to warrant an explicit demonstration. Let's rewrite the QCSORT.C program using pointer notation:
/* QCSORT1.C: Demonstrate sort with pointer notation. */
#include <stdio.h>
#define SIZE 4
void sort( int size, double **p );
void show( int size, double **p, double dd[] );
main()
{
int x;
double d[] = { 3.333, 1.111, 2.222, 4.444 };
double *d_ptr[SIZE];
for( x = 0; x < SIZE; x++ )
d_ptr[x] = &d[x];
show( SIZE, d_ptr, d );
sort( SIZE, d_ptr );
show( SIZE, d_ptr, d );
}
void sort( int size, double **p )
{
int x, x1;
double *temp;
for( x = 0; x < size - 1; x++ )
for( x1 = x + 1; x1 < size; x1++ )
{
if( **(p+x) > **(p+x1) )
{
temp = *(p+x1);
*(p+x1) = *(p+x);
*(p+x) = temp;
}
}
}
void show( int size, double **p, double dd[] )
{
int x;
printf( "------------------------" );
printf( "------------------------\n" );
for( x = 0; x < size; x++ )
{
printf( "*d_ptr[%d] = %1.3f ", x, **(p+x) );
printf( "d_ptr[%d] = %u ", x, *(p+x) );
printf( " d[%d] = %1.3f\n", x, dd[x] );
}
}
The QCSORT1.C program works like its predecessor, QCSORT.C. (It sorts an array of pointers that point to elements in an int array.) The only difference is QCSORT1.C uses pointer notation instead of array notation.
Let's look at how the change affects the sort function, beginning with its prototype. In the previous program, QCSORT.C, the prototype
void sort( int size, double *p[] );
uses array notation to show we'll pass the name of an array of pointers to sort. Since an array name is a pointer, we can rewrite the prototype using pointer notation, as in QCSORT1.C:
void sort( int size, double **p );
The sort function definition is rewritten in the same way. Here is the definition of sort in the original program (QCSORT.C):
void sort( int size, double *p[] )
{
int x, x1;
double *temp;
for( x = 0; x < size - 1; x++ )
for( x1 = x + 1; x1 < size; x1++ )
{
if( *p[x] > *p[x1] )
{
temp = p[x1];
p[x1] = p[x];
p[x] = temp;
}
}
}
The same function using pointers looks like this in QCSORT1.C:
void sort( int size, double **p )
{
int x, x1;
double *temp;
for( x = 0; x < size - 1; x++ )
for( x1 = x + 1; x1 < size; x1++ )
{
if( **(p+x) > **(p+x1) )
{
temp = *(p+x1);
*(p+x1) = *(p+x);
*(p+x) = temp;
}
}
}
Within the sort function, the variable p is a pointer to a pointer. When we use a single asterisk, as in,
*(p+x1)
we access the contents of the x1 pointer, which is an address. When we place a double asterisk in front of an address value, as in,
**(p+x)
we access the contents of this address.
Using pointer notation in place of array notation, QCSORT1.C achieves the same result as QCSORT.C. In many cases—including this one—it doesn't really matter which notation you use. If you're still more comfortable with array notation, you may prefer to use it sometimes. Since many C programs use pointers to manipulate arrays, however, it's worth taking the time to learn pointer notation, too.