CH 12
CH 12
i nt a[ N] , sum, *p;
sum= 0;
f or ( p = &a[ 0] ; p < &a[ N] ; p++)
sum+= *p;
Copyright 2008 W. W. Norton & Company.
All rights reserved.
13
Chapter 12: Pointers and Arrays
Using Pointers for Array Processing
At the end of the first iteration:
At the end of the second iteration:
At the end of the third iteration:
Copyright 2008 W. W. Norton & Company.
All rights reserved.
14
Chapter 12: Pointers and Arrays
Using Pointers for Array Processing
The condition p < &a[ N] in the f or statement
deserves special mention.
Its legal to apply the address operator to a[ N] ,
even though this element doesnt exist.
Pointer arithmetic may save execution time.
However, some C compilers produce better code
for loops that rely on subscripting.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
15
Chapter 12: Pointers and Arrays
Combining the * and ++ Operators
C programmers often combine the * (indirection)
and ++operators.
A statement that modifies an array element and
then advances to the next element:
a[ i ++] = j ;
The corresponding pointer version:
*p++ = j ;
Because the postfix version of ++takes
precedence over *, the compiler sees this as
*( p++) = j ;
Copyright 2008 W. W. Norton & Company.
All rights reserved.
16
Chapter 12: Pointers and Arrays
Combining the * and ++ Operators
Possible combinations of * and ++:
Expression Meaning
*p++or *( p++) Value of expression is *p before increment;
increment p later
( *p) ++ Value of expression is *p before increment;
increment *p later
*++p or *( ++p) Increment p first;
value of expression is *p after increment
++*p or ++( *p) Increment *p first;
value of expression is *p after increment
Copyright 2008 W. W. Norton & Company.
All rights reserved.
17
Chapter 12: Pointers and Arrays
Combining the * and ++ Operators
The most common combination of * and ++is
*p++, which is handy in loops.
Instead of writing
f or ( p = &a[ 0] ; p < &a[ N] ; p++)
sum+= *p;
to sum the elements of the array a, we could write
p = &a[ 0] ;
whi l e ( p < &a[ N] )
sum+= *p++;
Copyright 2008 W. W. Norton & Company.
All rights reserved.
18
Chapter 12: Pointers and Arrays
Combining the * and ++ Operators
The * and - - operators mix in the same way as *
and ++.
For an application that combines * and - - , lets
return to the stack example of Chapter 10.
The original version of the stack relied on an
integer variable named t op to keep track of the
top-of-stack position in the contents array.
Lets replace t op by a pointer variable that points
initially to element 0 of the cont ent s array:
i nt *t op_pt r = &cont ent s[ 0] ;
Copyright 2008 W. W. Norton & Company.
All rights reserved.
19
Chapter 12: Pointers and Arrays
Combining the * and ++ Operators
The new push and pop functions:
voi d push( i nt i )
{
i f ( i s_f ul l ( ) )
st ack_over f l ow( ) ;
el se
*t op_pt r ++ = i ;
}
i nt pop( voi d)
{
i f ( i s_empt y( ) )
st ack_under f l ow( ) ;
el se
r et ur n *- - t op_pt r ;
}
Copyright 2008 W. W. Norton & Company.
All rights reserved.
20
Chapter 12: Pointers and Arrays
Using an Array Name as a Pointer
Pointer arithmetic is one way in which arrays and
pointers are related.
Another key relationship:
The name of an array can be used as a pointer to
the first element in the array.
This relationship simplifies pointer arithmetic and
makes both arrays and pointers more versatile.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
21
Chapter 12: Pointers and Arrays
Using an Array Name as a Pointer
Suppose that a is declared as follows:
i nt a[ 10] ;
Examples of using a as a pointer:
*a = 7; / * st or es 7 i n a[ 0] */
*( a+1) = 12; / * st or es 12 i n a[ 1] */
In general, a +i is the same as &a[ i ] .
Both represent a pointer to element i of a.
Also, *( a+i ) is equivalent to a[ i ] .
Both represent element i itself.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
22
Chapter 12: Pointers and Arrays
Using an Array Name as a Pointer
The fact that an array name can serve as a pointer
makes it easier to write loops that step through an
array.
Original loop:
f or ( p = &a[ 0] ; p < &a[ N] ; p++)
sum+= *p;
Simplified version:
f or ( p = a; p < a + N; p++)
sum+= *p;
Copyright 2008 W. W. Norton & Company.
All rights reserved.
23
Chapter 12: Pointers and Arrays
Using an Array Name as a Pointer
Although an array name can be used as a pointer,
its not possible to assign it a new value.
Attempting to make it point elsewhere is an error:
whi l e ( *a ! = 0)
a++; / *** WRONG ***/
This is no great loss; we can always copy a into a
pointer variable, then change the pointer variable:
p = a;
whi l e ( *p ! = 0)
p++;
Copyright 2008 W. W. Norton & Company.
All rights reserved.
24
Chapter 12: Pointers and Arrays
Program: Reversing a Series
of Numbers (Revisited)
The r ever se. c program of Chapter 8 reads 10
numbers, then writes the numbers in reverse order.
The original program stores the numbers in an
array, with subscripting used to access elements of
the array.
r ever se3. c is a new version of the program in
which subscripting has been replaced with pointer
arithmetic.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
25
Chapter 12: Pointers and Arrays
reverse3.c
/ * Rever ses a ser i es of number s ( poi nt er ver si on) */
#i ncl ude <st di o. h>
#def i ne N 10
i nt mai n( voi d)
{
i nt a[ N] , *p;
pr i nt f ( "Ent er %d number s: ", N) ;
f or ( p = a; p < a + N; p++)
scanf ( "%d", p) ;
pr i nt f ( "I n r ever se or der : ") ;
f or ( p = a + N - 1; p >= a; p- - )
pr i nt f ( " %d", *p) ;
pr i nt f ( "\ n") ;
r et ur n 0;
}
Copyright 2008 W. W. Norton & Company.
All rights reserved.
26
Chapter 12: Pointers and Arrays
Array Arguments (Revisited)
When passed to a function, an array name is treated as a pointer.
Example:
i nt f i nd_l ar gest ( i nt a[ ] , i nt n)
{
i nt i , max;
max = a[ 0] ;
f or ( i = 1; i < n; i ++)
i f ( a[ i ] > max)
max = a[ i ] ;
r et ur n max;
}
A call of f i nd_l ar gest :
l ar gest = f i nd_l ar gest ( b, N) ;
This call causes a pointer to the first element of b to be assigned
to a; the array itself isnt copied.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
27
Chapter 12: Pointers and Arrays
Array Arguments (Revisited)
The fact that an array argument is treated as a
pointer has some important consequences.
Consequence 1: When an ordinary variable is
passed to a function, its value is copied; any
changes to the corresponding parameter dont
affect the variable.
In contrast, an array used as an argument isnt
protected against change.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
28
Chapter 12: Pointers and Arrays
Array Arguments (Revisited)
For example, the following function modifies an
array by storing zero into each of its elements:
voi d st or e_zer os( i nt a[ ] , i nt n)
{
i nt i ;
f or ( i = 0; i < n; i ++)
a[ i ] = 0;
}
Copyright 2008 W. W. Norton & Company.
All rights reserved.
29
Chapter 12: Pointers and Arrays
Array Arguments (Revisited)
To indicate that an array parameter wont be
changed, we can include the word const in its
declaration:
i nt f i nd_l ar gest ( const i nt a[ ] , i nt n)
{
}
If const is present, the compiler will check that
no assignment to an element of a appears in the
body of f i nd_l ar gest .
Copyright 2008 W. W. Norton & Company.
All rights reserved.
30
Chapter 12: Pointers and Arrays
Array Arguments (Revisited)
Consequence 2: The time required to pass an array
to a function doesnt depend on the size of the
array.
Theres no penalty for passing a large array, since
no copy of the array is made.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
31
Chapter 12: Pointers and Arrays
Array Arguments (Revisited)
Consequence 3: An array parameter can be
declared as a pointer if desired.
f i nd_l ar gest could be defined as follows:
i nt f i nd_l ar gest ( i nt *a, i nt n)
{
}
Declaring a to be a pointer is equivalent to
declaring it to be an array; the compiler treats the
declarations as though they were identical.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
32
Chapter 12: Pointers and Arrays
Array Arguments (Revisited)
Although declaring a parameter to be an array is
the same as declaring it to be a pointer, the same
isnt true for a variable.
The following declaration causes the compiler to
set aside space for 10 integers:
i nt a[ 10] ;
The following declaration causes the compiler to
allocate space for a pointer variable:
i nt *a;
Copyright 2008 W. W. Norton & Company.
All rights reserved.
33
Chapter 12: Pointers and Arrays
Array Arguments (Revisited)
In the latter case, a is not an array; attempting to
use it as an array can have disastrous results.
For example, the assignment
*a = 0; / *** WRONG ***/
will store 0 where a is pointing.
Since we dont know where a is pointing, the
effect on the program is undefined.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
34
Chapter 12: Pointers and Arrays
Array Arguments (Revisited)
Consequence 4: A function with an array
parameter can be passed an array slicea
sequence of consecutive elements.
An example that applies f i nd_l ar gest to
elements 5 through 14 of an array b:
l ar gest = f i nd_l ar gest ( &b[ 5] , 10) ;
Copyright 2008 W. W. Norton & Company.
All rights reserved.
35
Chapter 12: Pointers and Arrays
Using a Pointer as an Array Name
C allows us to subscript a pointer as though it
were an array name:
#def i ne N 10
i nt a[ N] , i , sum= 0, *p = a;
f or ( i = 0; i < N; i ++)
sum+= p[ i ] ;
The compiler treats p[ i ] as *( p+i ) .
Copyright 2008 W. W. Norton & Company.
All rights reserved.
36
Chapter 12: Pointers and Arrays
Pointers and Multidimensional Arrays
J ust as pointers can point to elements of one-
dimensional arrays, they can also point to
elements of multidimensional arrays.
This section explores common techniques for
using pointers to process the elements of
multidimensional arrays.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
37
Chapter 12: Pointers and Arrays
Processing the Elements
of a Multidimensional Array
Chapter 8 showed that C stores two-dimensional
arrays in row-major order.
Layout of an array with r rows:
If p initially points to the element in row 0, column 0,
we can visit every element in the array by
incrementing p repeatedly.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
38
Chapter 12: Pointers and Arrays
Processing the Elements
of a Multidimensional Array
Consider the problem of initializing all elements of the following
array to zero:
i nt a[ NUM_ROWS] [ NUM_COLS] ;
The obvious technique would be to use nested f or loops:
i nt r ow, col ;
}
Copyright 2008 W. W. Norton & Company.
All rights reserved.
49
Chapter 12: Pointers and Arrays
Pointers and Variable-Length Arrays (C99)
When the VLA has more than one dimension, the
type of the pointer depends on the length of each
dimension except for the first.
A two-dimensional example:
voi d f ( i nt m, i nt n)
{
i nt a[ m] [ n] , ( *p) [ n] ;
p = a;
}
Since the type of p depends on n, which isnt
constant, p is said to have a variably modified type.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
50
Chapter 12: Pointers and Arrays
Pointers and Variable-Length Arrays (C99)
The validity of an assignment such as p =a cant
always be determined by the compiler.
The following code will compile but is correct
only if mand n are equal:
i nt a[ m] [ n] , ( *p) [ m] ;
p = a;
If mis not equal to n, any subsequent use of p will
cause undefined behavior.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
51
Chapter 12: Pointers and Arrays
Pointers and Variable-Length Arrays (C99)
Variably modified types are subject to certain
restrictions.
The most important restriction: the declaration of
a variably modified type must be inside the body
of a function or in a function prototype.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
52
Chapter 12: Pointers and Arrays
Pointers and Variable-Length Arrays (C99)
Pointer arithmetic works with VLAs.
A two-dimensional VLA:
i nt a[ m] [ n] ;
A pointer capable of pointing to a row of a:
i nt ( *p) [ n] ;
A loop that clears column i of a:
f or ( p = a; p < a + m; p++)
( *p) [ i ] = 0;
Copyright 2008 W. W. Norton & Company.
All rights reserved.
53