1 <!DOCTYPE HTML PUBLIC
"-//W3O//DTD W3 HTML 2.0//EN">
2 <!-- This collection of hypertext pages is Copyright 1995, 1996 by Steve Summit. -->
3 <!-- This material may be freely redistributed and used -->
4 <!-- but may not be republished or sold without permission. -->
7 <link rev=
"owner" href=
"mailto:scs@eskimo.com">
8 <link rev=
"made" href=
"mailto:scs@eskimo.com">
9 <title>section
5.2: Pointers and Function Arguments
</title>
10 <link href=
"sx8a.html" rev=precedes
>
11 <link href=
"sx8c.html" rel=precedes
>
12 <link href=
"sx8.html" rev=subdocument
>
15 <H2>section
5.2: Pointers and Function Arguments
</H2>
18 <p>This section discusses a very common use of pointers:
19 setting things up so that a function can modify values in its caller,
24 C passes arguments by value,
25 and that if a function modifies one of its arguments,
26 it modifies only its local copy,
27 not the value in the caller.
30 having a function which inadvertently assigns to its arguments
31 and hence inadvertently modifies a value in its caller
33 can be a source of obscure bugs in languages which don't use call-by-value.)
35 what happens if a function wants to modify a value in its caller,
36 and its caller wants to let it?
37 How can a function return two values?
38 (A function's formal return value is always a single value.)
39 </p><p>The answer to both questions
40 is that a function can declare a parameter which is a pointer.
41 The caller then passes a pointer to
42 (that is, the ``address of'')
43 a variable in the caller which is to be modified
44 or which is to receive the second return value.
46 we've seen examples of this already:
47 <TT>getline
</TT> returns the length of the line it reads
48 as well as the line itself,
50 the
<TT>getop
</TT> routine in the calculator example
52 returned both a code for an operator
53 and a string representing the full text of the operator.
56 when the operator was
<TT>'
0'
</TT> indicating numeric input,
57 so that the string could return
58 the full numeric input.)
59 Though we didn't say so at the time,
60 we were actually using pointers
62 (We'll explore the relationship between arrays and pointers,
63 which made this possible,
65 </p><p>With all of this in mind,
66 make sure that you understand why the swap example on page
95
68 and how and why the swap example on page
96 <em>does
</em> work,
69 and what the figure on page
96 shows.
70 </p><p>The
<TT>swap
</TT> example demonstrated a function
71 which modified some variables
72 (
<TT>a
</TT> and
<TT>b
</TT>)
74 The
<TT>getint
</TT> example demonstrates
75 how to return two values from a function
76 by returning one value as the normal function return value
77 and the other one by writing to a pointer.
79 is no fundamental difference,
82 ``modifying a variable in the caller''
84 ``returning a value by writing to a pointer'';
85 these are just two applications of pointer parameters.)
86 </p><p>The version of
<TT>getint
</TT> on page
97
87 is somewhat complicated because it
88 allows free-form input,
90 the values need only be separated by whitespace or punctuation;
91 they are not restricted to being one per line or anything.
92 (C source code is also free-form in this regard;
93 see page
4 of chapter
1 of these notes.)
95 the essence of what
<TT>getint
</TT> is supposed to do,
96 imagine for a moment that
97 the input
<em>is
</em> restricted to one value per line,
98 as in the ``primitive calculator'' example on page
72 of section
4.2.
100 we might use the following simpler
101 (i.e. more primitive)
103 <pre> int getint(int *pn)
106 if (getline(line,
20)
<=
0)
111 </pre>The
<TT>getint
</TT> function on page
97 is
112 documented as returning nonzero for a valid number and
0 for
113 something other than a number.
114 Our stripped-down version does not,
116 the example code at the bottom of page
96 does not make use of
117 the valid/invalid distinction.
118 Can you see a way to rewrite the code at the bottom of page
96
119 to fill in the cells of the
<TT>array
</TT> with only valid numbers?
120 </p><p>You might also notice,
121 again from the code at the bottom of page
96,
122 that
<TT>&</TT> need not be restricted to single, simple variables;
123 it can take the address of any data object,
125 one cell of the
<TT>array
</TT>.
126 Just as for all of C's other operators,
127 <TT>&</TT> can be applied to arbitrary expressions,
128 although it is restricted to expressions which represent
131 <TT>&1</TT> or
<TT>&(
2+
3)
</TT>
132 are meaningless and illegal.
133 </p><p>You may remember a discussion from section
1.5.1 on page
16
134 of how C's
<TT>getchar
</TT> routine is able to return all possible characters,
135 plus an end-of-file indication,
136 in its single return value.
137 Why does
<TT>getint
</TT> need two return values?
138 Why can't it use the same trick that
<TT>getchar
</TT> does?
139 </p><p>The examples in this section are again relatively safe.
140 The pointers have all been parameters,
141 and the callers have passed pointers
142 (that is, the ``addresses'' of)
143 their own, properly-allocated variables.
146 <pre> int a =
1, b =
2;
147 swap(
&a,
&b);
151 </pre>is correct and quite safe.
152 </p><p>Something to beware of,
154 is the temptation to inadvertently pass an uninitialized pointer variable
155 (rather than the ``address'' of some other
157 to a routine which expects a pointer.
158 We know that the
<TT>getint
</TT> routine expects
160 a pointer to an
<TT>int
</TT> in which it is to store the integer it gets.
161 Suppose we took that description literally,
163 <pre> int *ip; /* a pointer to an int */
165 </pre>Here we have in fact passed a pointer-to-
<TT>int
</TT> to
<TT>getint
</TT>,
166 but the pointer we passed doesn't point anywhere!
167 When
<TT>getint
</TT> writes to (``dereferences'')
168 the pointer, in an expression like
<TT>*pn =
0</TT>,
169 it will scribble on some random part of memory,
170 and the program may crash.
171 When people get caught in this trap,
172 they often think that to fix it they need to use the
<TT>&</TT> operator:
173 <pre> getint(
&ip); /* WRONG */
174 </pre>or maybe the
<TT>*
</TT> operator:
175 <pre> getint(*ip); /* WRONG */
176 </pre>but these go from bad to worse.
177 (If you think about them carefully,
178 <TT>&ip
</TT> is a pointer-to-pointer-to-
<TT>int
</TT>,
179 and
<TT>*ip
</TT> is an
<TT>int
</TT>,
180 and neither of these types matches the pointer-to-
<TT>int
</TT>
181 which
<TT>getint
</TT> expects.)
182 The correct usage for now,
183 as we showed already,
188 <TT>a
</TT> is an honest-to-goodness, allocated
<TT>int
</TT>,
189 so when we generate a pointer to it
190 (with
<TT>&a
</TT>)
191 and call
<TT>getint
</TT>,
192 <TT>getint
</TT> receives a pointer that does point somewhere.
196 <a href=
"sx8a.html" rev=precedes
>prev
</a>
197 <a href=
"sx8c.html" rel=precedes
>next
</a>
198 <a href=
"sx8.html" rev=subdocument
>up
</a>
199 <a href=
"top.html">top
</a>
202 This page by
<a href=
"http://www.eskimo.com/~scs/">Steve Summit
</a>
203 //
<a href=
"copyright.html">Copyright
</a> 1995,
1996
204 //
<a href=
"mailto:scs@eskimo.com">mail feedback
</a>