Page 1
CHARACTER POINTERS AND FUNCTIONS
A string constant, written as
"I am a s tr in g "
is an array of characters. In the internal representation, the array is terminated with the null
character ' \ 0 ' so that programs can find the end. The length in storage is thus one more than the
number of characters between the double quotes.
Perhaps the most common occurrence of string constants is as arguments to functions, as in
p r i n t f ( " h e l l o , w orld\n");
When a character string like this appears in a program, access to it is through a character pointer;
p r i n t f receives a pointer to the beginning of the character array. That is, a string constant is
accessed by a pointer to its first element. String constants need not be function arguments. If
pmessageis declared as
char *pmessage;
then the statement
pmessage = "now is the time";
assigns to pmessagea pointer to the character array. This is not a string copy; only pointers are
involved. C does not provide any operators for processing an entire string of characters as a unit.
There is an important difference between these definitions:
char amessage[] = "now is the time";
char *pmessage = "now is the time";
amessage is an array, just big enough to hold the sequence of characters and ' \ 0 ' that initializes
it. Individual characters within the array may be changed but amessagewill always refer to the
same storage. On the other hand, pmessageis a pointer, initialized to point to a string constant; the
pointer may subsequently be modified to point elsewhere, but the result is undefined if you try to
modify the string contents.
We will illustrate more aspects of pointers and arrays by studying versions of two useful
functions adapted from the standard library. The first function is s t r c p y (s , t ), which copies the
string t to the string s . It would be nice just to say s=t but this copies the pointer, not the
characters. To copy the characters, we need a loop. The array version first:
void s trc p y (c h a r *s, char *t)
{
i n t i ;
i = 0;
while (( s [ i] = t [ i ] ) != ' \0 ')
i++;
Page 2
CHARACTER POINTERS AND FUNCTIONS
A string constant, written as
"I am a s tr in g "
is an array of characters. In the internal representation, the array is terminated with the null
character ' \ 0 ' so that programs can find the end. The length in storage is thus one more than the
number of characters between the double quotes.
Perhaps the most common occurrence of string constants is as arguments to functions, as in
p r i n t f ( " h e l l o , w orld\n");
When a character string like this appears in a program, access to it is through a character pointer;
p r i n t f receives a pointer to the beginning of the character array. That is, a string constant is
accessed by a pointer to its first element. String constants need not be function arguments. If
pmessageis declared as
char *pmessage;
then the statement
pmessage = "now is the time";
assigns to pmessagea pointer to the character array. This is not a string copy; only pointers are
involved. C does not provide any operators for processing an entire string of characters as a unit.
There is an important difference between these definitions:
char amessage[] = "now is the time";
char *pmessage = "now is the time";
amessage is an array, just big enough to hold the sequence of characters and ' \ 0 ' that initializes
it. Individual characters within the array may be changed but amessagewill always refer to the
same storage. On the other hand, pmessageis a pointer, initialized to point to a string constant; the
pointer may subsequently be modified to point elsewhere, but the result is undefined if you try to
modify the string contents.
We will illustrate more aspects of pointers and arrays by studying versions of two useful
functions adapted from the standard library. The first function is s t r c p y (s , t ), which copies the
string t to the string s . It would be nice just to say s=t but this copies the pointer, not the
characters. To copy the characters, we need a loop. The array version first:
void s trc p y (c h a r *s, char *t)
{
i n t i ;
i = 0;
while (( s [ i] = t [ i ] ) != ' \0 ')
i++;
}
For contrast, here is a version of s trc p y with pointers:
void s trc p y (c h a r *s, char *t)
{
i n t i ;
i = 0;
while ((*s = *t) != ' \0 ')
{ s++; t++; }
}
Because arguments are passed by value, s trc p y can use the parameters s and t in any way it
pleases. Here they are conveniently initialized pointers, which are marched along the arrays a
character at a time, until the ' \ 0 ' that terminates t has been copied into s . In practice,
s trc p y would not be written as we showed it above. Experienced C programmers would prefer
void s trc p y (c h a r *s, char *t)
{
while ((*s++ = *t++) != '\ 0 ')
;
}
This moves the increment of s and t into the test part of the loop. The value of *t ++ is the
character that t pointed to before t was incremented; the postfix ++ doesn't change t until after
this character has been fetched. In the same way, the character is stored into the old s position
before s is incremented. This character is also the value that is compared against ' \ 0 ' to control
the loop. The net effect is that characters are copied from t to s , up and including the terminating
' \ 0 ' .
As the final abbreviation, observe that a comparison against ' \ 0 ' is redundant, since the question
is merely whether the expression is zero. So the function would likely be written as
void s trc p y (c h a r *s, char *t)
{
while (*s++ = *t++)
;
}
Although this may seem cryptic at first sight, the notational convenience is considerable, and the
idiom should be mastered, because you will see it frequently in C programs. The s trc p y in the
standard library (<s t r i n g . h>) returns the target string as its function value. The second routine
that we will examine is strcm p (s , t ), which compares the character strings s and t , and returns
negative, zero or positive if s is lexicographically less than, equal to, or greater than t . The value
is obtained by subtracting the characters at the first position where s and t disagree.
i n t strcm p(char *s, char *t)
Page 3
CHARACTER POINTERS AND FUNCTIONS
A string constant, written as
"I am a s tr in g "
is an array of characters. In the internal representation, the array is terminated with the null
character ' \ 0 ' so that programs can find the end. The length in storage is thus one more than the
number of characters between the double quotes.
Perhaps the most common occurrence of string constants is as arguments to functions, as in
p r i n t f ( " h e l l o , w orld\n");
When a character string like this appears in a program, access to it is through a character pointer;
p r i n t f receives a pointer to the beginning of the character array. That is, a string constant is
accessed by a pointer to its first element. String constants need not be function arguments. If
pmessageis declared as
char *pmessage;
then the statement
pmessage = "now is the time";
assigns to pmessagea pointer to the character array. This is not a string copy; only pointers are
involved. C does not provide any operators for processing an entire string of characters as a unit.
There is an important difference between these definitions:
char amessage[] = "now is the time";
char *pmessage = "now is the time";
amessage is an array, just big enough to hold the sequence of characters and ' \ 0 ' that initializes
it. Individual characters within the array may be changed but amessagewill always refer to the
same storage. On the other hand, pmessageis a pointer, initialized to point to a string constant; the
pointer may subsequently be modified to point elsewhere, but the result is undefined if you try to
modify the string contents.
We will illustrate more aspects of pointers and arrays by studying versions of two useful
functions adapted from the standard library. The first function is s t r c p y (s , t ), which copies the
string t to the string s . It would be nice just to say s=t but this copies the pointer, not the
characters. To copy the characters, we need a loop. The array version first:
void s trc p y (c h a r *s, char *t)
{
i n t i ;
i = 0;
while (( s [ i] = t [ i ] ) != ' \0 ')
i++;
}
For contrast, here is a version of s trc p y with pointers:
void s trc p y (c h a r *s, char *t)
{
i n t i ;
i = 0;
while ((*s = *t) != ' \0 ')
{ s++; t++; }
}
Because arguments are passed by value, s trc p y can use the parameters s and t in any way it
pleases. Here they are conveniently initialized pointers, which are marched along the arrays a
character at a time, until the ' \ 0 ' that terminates t has been copied into s . In practice,
s trc p y would not be written as we showed it above. Experienced C programmers would prefer
void s trc p y (c h a r *s, char *t)
{
while ((*s++ = *t++) != '\ 0 ')
;
}
This moves the increment of s and t into the test part of the loop. The value of *t ++ is the
character that t pointed to before t was incremented; the postfix ++ doesn't change t until after
this character has been fetched. In the same way, the character is stored into the old s position
before s is incremented. This character is also the value that is compared against ' \ 0 ' to control
the loop. The net effect is that characters are copied from t to s , up and including the terminating
' \ 0 ' .
As the final abbreviation, observe that a comparison against ' \ 0 ' is redundant, since the question
is merely whether the expression is zero. So the function would likely be written as
void s trc p y (c h a r *s, char *t)
{
while (*s++ = *t++)
;
}
Although this may seem cryptic at first sight, the notational convenience is considerable, and the
idiom should be mastered, because you will see it frequently in C programs. The s trc p y in the
standard library (<s t r i n g . h>) returns the target string as its function value. The second routine
that we will examine is strcm p (s , t ), which compares the character strings s and t , and returns
negative, zero or positive if s is lexicographically less than, equal to, or greater than t . The value
is obtained by subtracting the characters at the first position where s and t disagree.
i n t strcm p(char *s, char *t)
{
i n t i ;
fo r (i = 0; s [ i] == t [ i ] ; i++)
i f (s[i] == '\ 0 ')
re tu rn 0;
re tu rn s [ i] - t [ i ] ;
}
The pointer version of strcmp:
i n t strcm p(char *s, char *t)
{
fo r ( ; *s == *t; s++, t++)
i f (*s == '\ 0 ')
re tu rn 0;
re tu rn *s - *t;
}
Since ++ and -- are either prefix or postfix operators, other combinations of * and ++ and -
occur, although less frequently. For example,
*--p
decrements p before fetching the character that p points to. In fact, the pair of expressions
*p++ = v al;
val = *--p;
are the standard idiom for pushing and popping a stack;The header <string.h> contains
declarations for the functions mentioned in this section, plus a variety of other string-handling
functions from the standard library.
Page 4
CHARACTER POINTERS AND FUNCTIONS
A string constant, written as
"I am a s tr in g "
is an array of characters. In the internal representation, the array is terminated with the null
character ' \ 0 ' so that programs can find the end. The length in storage is thus one more than the
number of characters between the double quotes.
Perhaps the most common occurrence of string constants is as arguments to functions, as in
p r i n t f ( " h e l l o , w orld\n");
When a character string like this appears in a program, access to it is through a character pointer;
p r i n t f receives a pointer to the beginning of the character array. That is, a string constant is
accessed by a pointer to its first element. String constants need not be function arguments. If
pmessageis declared as
char *pmessage;
then the statement
pmessage = "now is the time";
assigns to pmessagea pointer to the character array. This is not a string copy; only pointers are
involved. C does not provide any operators for processing an entire string of characters as a unit.
There is an important difference between these definitions:
char amessage[] = "now is the time";
char *pmessage = "now is the time";
amessage is an array, just big enough to hold the sequence of characters and ' \ 0 ' that initializes
it. Individual characters within the array may be changed but amessagewill always refer to the
same storage. On the other hand, pmessageis a pointer, initialized to point to a string constant; the
pointer may subsequently be modified to point elsewhere, but the result is undefined if you try to
modify the string contents.
We will illustrate more aspects of pointers and arrays by studying versions of two useful
functions adapted from the standard library. The first function is s t r c p y (s , t ), which copies the
string t to the string s . It would be nice just to say s=t but this copies the pointer, not the
characters. To copy the characters, we need a loop. The array version first:
void s trc p y (c h a r *s, char *t)
{
i n t i ;
i = 0;
while (( s [ i] = t [ i ] ) != ' \0 ')
i++;
}
For contrast, here is a version of s trc p y with pointers:
void s trc p y (c h a r *s, char *t)
{
i n t i ;
i = 0;
while ((*s = *t) != ' \0 ')
{ s++; t++; }
}
Because arguments are passed by value, s trc p y can use the parameters s and t in any way it
pleases. Here they are conveniently initialized pointers, which are marched along the arrays a
character at a time, until the ' \ 0 ' that terminates t has been copied into s . In practice,
s trc p y would not be written as we showed it above. Experienced C programmers would prefer
void s trc p y (c h a r *s, char *t)
{
while ((*s++ = *t++) != '\ 0 ')
;
}
This moves the increment of s and t into the test part of the loop. The value of *t ++ is the
character that t pointed to before t was incremented; the postfix ++ doesn't change t until after
this character has been fetched. In the same way, the character is stored into the old s position
before s is incremented. This character is also the value that is compared against ' \ 0 ' to control
the loop. The net effect is that characters are copied from t to s , up and including the terminating
' \ 0 ' .
As the final abbreviation, observe that a comparison against ' \ 0 ' is redundant, since the question
is merely whether the expression is zero. So the function would likely be written as
void s trc p y (c h a r *s, char *t)
{
while (*s++ = *t++)
;
}
Although this may seem cryptic at first sight, the notational convenience is considerable, and the
idiom should be mastered, because you will see it frequently in C programs. The s trc p y in the
standard library (<s t r i n g . h>) returns the target string as its function value. The second routine
that we will examine is strcm p (s , t ), which compares the character strings s and t , and returns
negative, zero or positive if s is lexicographically less than, equal to, or greater than t . The value
is obtained by subtracting the characters at the first position where s and t disagree.
i n t strcm p(char *s, char *t)
{
i n t i ;
fo r (i = 0; s [ i] == t [ i ] ; i++)
i f (s[i] == '\ 0 ')
re tu rn 0;
re tu rn s [ i] - t [ i ] ;
}
The pointer version of strcmp:
i n t strcm p(char *s, char *t)
{
fo r ( ; *s == *t; s++, t++)
i f (*s == '\ 0 ')
re tu rn 0;
re tu rn *s - *t;
}
Since ++ and -- are either prefix or postfix operators, other combinations of * and ++ and -
occur, although less frequently. For example,
*--p
decrements p before fetching the character that p points to. In fact, the pair of expressions
*p++ = v al;
val = *--p;
are the standard idiom for pushing and popping a stack;The header <string.h> contains
declarations for the functions mentioned in this section, plus a variety of other string-handling
functions from the standard library.
Pointer Arrays; Pointers to Pointers
Syntax to declare pointer to an array is
datatype (*pointer_variable)[size];
For example
int (*ptr)[10]; ,Here ptr is a pointer that can point to an array of 10 integers, where we can
initialize ptr with the base address of the array then by incre menting the value of ptr we can
access different elements of array a[].
Since pointers are variables themselves, they can be stored in arrays just as other variables can.
Let us illustrate by writing a program that will sort a set of text lines into alphabetic order, a
stripped-down version of the UNIX program sort.
We need a data representation that will cope efficiently and conveniently with variable-length text
lines. This is where the array of pointers enters. If the lines to be sorted are stored end-to-end in
one long character array, then each line can be accessed by a pointer to its first character.
Thepointers themselves can bee stored in an array. Two lines can be compared by passing their
pointers to strcm p. When two out-of-order lines have to be exchanged, the pointers in the pointer
array are exchanged, not the text lines themselves.
This eliminates the twin problems of complicated storage management and high overhead that
would go with moving the lines themselves.
The sorting process has three steps:
read all the lines of input
sort them
print them in order
As usual, it's best to divide the program into functions that match this natural division, with the
main routine controlling the other functions. Let us defer the sorting step for a moment, and
concentrate on the data structure and the input and output. The input routine has to collect and
save the characters of each line, and build an array of pointers to the lines. It will also have to
count the number of input lines, since that information is needed for sorting and printing. Since
the input function can only cope with a finite number of input lines, it can return some illegal
count like -1 if too much input is presented. The output routine only has to print the lines in the
order in which they appear in the array of pointers.
#include < stdio.h>
#include < strin g .h >
#define MAXLINES 5000
char *lineptr[MAXLINES];
i n t r e a d li n e s ( c h a r * l i n e p t r [ ] , i n t n l i n e s ) ;
Page 5
CHARACTER POINTERS AND FUNCTIONS
A string constant, written as
"I am a s tr in g "
is an array of characters. In the internal representation, the array is terminated with the null
character ' \ 0 ' so that programs can find the end. The length in storage is thus one more than the
number of characters between the double quotes.
Perhaps the most common occurrence of string constants is as arguments to functions, as in
p r i n t f ( " h e l l o , w orld\n");
When a character string like this appears in a program, access to it is through a character pointer;
p r i n t f receives a pointer to the beginning of the character array. That is, a string constant is
accessed by a pointer to its first element. String constants need not be function arguments. If
pmessageis declared as
char *pmessage;
then the statement
pmessage = "now is the time";
assigns to pmessagea pointer to the character array. This is not a string copy; only pointers are
involved. C does not provide any operators for processing an entire string of characters as a unit.
There is an important difference between these definitions:
char amessage[] = "now is the time";
char *pmessage = "now is the time";
amessage is an array, just big enough to hold the sequence of characters and ' \ 0 ' that initializes
it. Individual characters within the array may be changed but amessagewill always refer to the
same storage. On the other hand, pmessageis a pointer, initialized to point to a string constant; the
pointer may subsequently be modified to point elsewhere, but the result is undefined if you try to
modify the string contents.
We will illustrate more aspects of pointers and arrays by studying versions of two useful
functions adapted from the standard library. The first function is s t r c p y (s , t ), which copies the
string t to the string s . It would be nice just to say s=t but this copies the pointer, not the
characters. To copy the characters, we need a loop. The array version first:
void s trc p y (c h a r *s, char *t)
{
i n t i ;
i = 0;
while (( s [ i] = t [ i ] ) != ' \0 ')
i++;
}
For contrast, here is a version of s trc p y with pointers:
void s trc p y (c h a r *s, char *t)
{
i n t i ;
i = 0;
while ((*s = *t) != ' \0 ')
{ s++; t++; }
}
Because arguments are passed by value, s trc p y can use the parameters s and t in any way it
pleases. Here they are conveniently initialized pointers, which are marched along the arrays a
character at a time, until the ' \ 0 ' that terminates t has been copied into s . In practice,
s trc p y would not be written as we showed it above. Experienced C programmers would prefer
void s trc p y (c h a r *s, char *t)
{
while ((*s++ = *t++) != '\ 0 ')
;
}
This moves the increment of s and t into the test part of the loop. The value of *t ++ is the
character that t pointed to before t was incremented; the postfix ++ doesn't change t until after
this character has been fetched. In the same way, the character is stored into the old s position
before s is incremented. This character is also the value that is compared against ' \ 0 ' to control
the loop. The net effect is that characters are copied from t to s , up and including the terminating
' \ 0 ' .
As the final abbreviation, observe that a comparison against ' \ 0 ' is redundant, since the question
is merely whether the expression is zero. So the function would likely be written as
void s trc p y (c h a r *s, char *t)
{
while (*s++ = *t++)
;
}
Although this may seem cryptic at first sight, the notational convenience is considerable, and the
idiom should be mastered, because you will see it frequently in C programs. The s trc p y in the
standard library (<s t r i n g . h>) returns the target string as its function value. The second routine
that we will examine is strcm p (s , t ), which compares the character strings s and t , and returns
negative, zero or positive if s is lexicographically less than, equal to, or greater than t . The value
is obtained by subtracting the characters at the first position where s and t disagree.
i n t strcm p(char *s, char *t)
{
i n t i ;
fo r (i = 0; s [ i] == t [ i ] ; i++)
i f (s[i] == '\ 0 ')
re tu rn 0;
re tu rn s [ i] - t [ i ] ;
}
The pointer version of strcmp:
i n t strcm p(char *s, char *t)
{
fo r ( ; *s == *t; s++, t++)
i f (*s == '\ 0 ')
re tu rn 0;
re tu rn *s - *t;
}
Since ++ and -- are either prefix or postfix operators, other combinations of * and ++ and -
occur, although less frequently. For example,
*--p
decrements p before fetching the character that p points to. In fact, the pair of expressions
*p++ = v al;
val = *--p;
are the standard idiom for pushing and popping a stack;The header <string.h> contains
declarations for the functions mentioned in this section, plus a variety of other string-handling
functions from the standard library.
Pointer Arrays; Pointers to Pointers
Syntax to declare pointer to an array is
datatype (*pointer_variable)[size];
For example
int (*ptr)[10]; ,Here ptr is a pointer that can point to an array of 10 integers, where we can
initialize ptr with the base address of the array then by incre menting the value of ptr we can
access different elements of array a[].
Since pointers are variables themselves, they can be stored in arrays just as other variables can.
Let us illustrate by writing a program that will sort a set of text lines into alphabetic order, a
stripped-down version of the UNIX program sort.
We need a data representation that will cope efficiently and conveniently with variable-length text
lines. This is where the array of pointers enters. If the lines to be sorted are stored end-to-end in
one long character array, then each line can be accessed by a pointer to its first character.
Thepointers themselves can bee stored in an array. Two lines can be compared by passing their
pointers to strcm p. When two out-of-order lines have to be exchanged, the pointers in the pointer
array are exchanged, not the text lines themselves.
This eliminates the twin problems of complicated storage management and high overhead that
would go with moving the lines themselves.
The sorting process has three steps:
read all the lines of input
sort them
print them in order
As usual, it's best to divide the program into functions that match this natural division, with the
main routine controlling the other functions. Let us defer the sorting step for a moment, and
concentrate on the data structure and the input and output. The input routine has to collect and
save the characters of each line, and build an array of pointers to the lines. It will also have to
count the number of input lines, since that information is needed for sorting and printing. Since
the input function can only cope with a finite number of input lines, it can return some illegal
count like -1 if too much input is presented. The output routine only has to print the lines in the
order in which they appear in the array of pointers.
#include < stdio.h>
#include < strin g .h >
#define MAXLINES 5000
char *lineptr[MAXLINES];
i n t r e a d li n e s ( c h a r * l i n e p t r [ ] , i n t n l i n e s ) ;
void w r ite l in e s ( c h a r * l i n e p t r [ ] , i n t n l i n e s ) ;
void q s o rt(c h a r * l i n e p t r [ ] , i n t l e f t , i n t r i g h t ) ;
main()
{
in t n l i n e s ;
i f ((n lin e s = r e a d l i n e s ( l i n e p t r , MAXLINES)) >= 0) {
q s o r t ( l i n e p t r , 0, n lin e s - 1 ) ;
w r i t e l i n e s ( l i n e p t r , n li n e s ) ; re tu rn 0;
} e ls e {
p r i n t f ( " e r r o r : inp u t too big to s o r t \ n " ) ;
re tu r n 1;
}
}
#define MAXLEN 1000
i n t g e t l i n e ( c h a r *, i n t ) ;
char * a l l o c ( i n t ) ;
i n t r e a d li n e s ( c h a r * l i n e p t r [ ] , intm axlines)
{
in t l e n , n lin e s ;
char *p, line[MAXLEN];
n lin e s = 0;
while ((len = g e t l i n e ( l i n e , MAXLEN)) > 0)
i f (nlines>= maxlines || p = a llo c (le n ) == NULL)
r e tu rn -1;
e ls e {
lin e [ le n - 1 ] = ' \ 0 ' ; /* d e le te newline */
s trc p y (p , l i n e ) ;
lin e p tr[n lin e s + + ] = p;
}
re tu rn n lin e s ;
}
void w r ite l in e s ( c h a r * l i n e p t r [ ] , in tn lin e s )
{
i n t i ;
fo r (i = 0; i< n lin e s ; i++)
p rin tf(" % s \n " , l i n e p t r [ i ] ) ;
}
Read More