Summary: String pointers are handled like other array pointers.
Because a string is an array of characters, pointers to strings are handled much like other array pointers. The program PSTRING.C is similar to the examples that demonstrated array pointers (PARRAY.C and PARRAY1.C). It uses a pointer to access a char array:
/* PSTRING.C: Demonstrate pointer to a string. */
#include <stdio.h>
main()
{
int count;
char name[] = "john";
char *ptr = name;
for( count = 0; count < 4; count++ )
{
printf( "name[%d]: %c\n", count, *ptr++ );
}
}
The PSTRING.C program steps through the name array, printing each character in turn:
name[0]: j
name[1]: o
name[2]: h
name[3]: n
The notable difference between PARRAY.C and PSTRING.C is that PSTRING.C has a char array instead of an int array. Again, incrementing an array pointer moves the pointer to the next array element. So in PSTRING.C each iteration of the for loop moves the pointer to the next char in the string.
The first time through the loop, ptr points to name[0]. The second time it points to name[1], and so on.
As mentioned in Chapter 4, “Data Types,” one difference between strings and noncharacter arrays is that strings end with a null character. The string in PSTRING.C actually contains five characters: four letters and a null character. We can exploit this fact to simplify the program, as we do below in PSTRING.C.
/* PSTRING1.C: Look for null at string's end. */
#include <stdio.h>
main()
{
char name[] = "john";
char *ptr = name;
while( *ptr )
printf( "*ptr = %c\n", *ptr++ );
}
Here is the output from PSTRING1.C:
*ptr = j
*ptr = o
*ptr = h
*ptr = n
Like PSTRING.C, the PSTRING1.C program steps through the array one character at a time. However, it replaces the for loop with a simpler while loop. The test expression in the while loop,
while( *ptr )
is evaluated as true until ptr points to the null character that terminates the string. It's a more compact way of writing this expression:
while( *ptr != 0 )
Summary: Any operation done with array subscripts can also be done with pointer notation.
This is an ideal time to elaborate on the relationship between arrays and pointers. Any operation you can do with conventional array notation (subscripts) can also be done with pointers. This is possible because an array name, as we noted earlier, is itself a pointer.
To illustrate, the PSTRING2.C program uses only array notation:
/* PSTRING2.C: Demonstrate strings and array notation. */
#include <stdio.h>
#include <string.h>
main()
{
int count;
char name[] = "john";
for( count = 0; count < strlen( name ); count++ )
printf( "name[%d]: %c\n", count, name[count] );
}
PSTRING2.C gives the same output as PSTRING.C. In this program, the expression
name[count]
uses count as in an index to the name array.
PSTRING3.C is the same program written with pointer notation:
/* PSTRING3.C: Strings and pointer notation. */
#include <stdio.h>
#include <string.h>
main()
{
int count;
char name[] = "john";
for( count = 0; count < strlen( name ); count++ )
printf( "*(name+%d) = %c\n", count,*(name+count) );
}
Here is the output from PSTRING3.C:
*(name+0) = j
*(name+1) = o
*(name+2) = h
*(name+3) = n
Notice how PSTRING3.C replaces the expression
name[count]
with the expression:
*(name+count)
Both expressions use the variable count as an offset from the base address of the array. The parentheses in the second expression are important. They are necessary because the indirection operator takes effect before the addition operator. If you omit the parentheses, as in
*name+count
the expression has the same effect as
(*name)+count
which adds the value of count to the object name references.
In summary, the examples in this section show three alternative ways to access a character inside a string. In the printf statements in the examples, these expressions are equivalent:
*ptr
name[count]
*(name+count)
Many C programmers prefer pointer notation to array notation because pointers are faster for some operations. In other cases—including the one above—the choice is entirely one of taste. There's more to say about the relationship between pointers and arrays. We'll return to this topic later in this chapter and in Chapter 9, “Advanced Pointers.”