* X more docs for C
[mascara-docs.git] / C / the.ansi.c.programming.language / notes.accompany.ansi.c / sx8b.html
blobb84228a15a49a5b76e856f86ffe6404855f41b56
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. -->
5 <html>
6 <head>
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>
13 </head>
14 <body>
15 <H2>section 5.2: Pointers and Function Arguments</H2>
17 page 95
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,
20 or return values,
21 via its arguments.
22 Remember that,
23 normally,
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.
28 (Normally,
29 this is a good thing;
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.)
34 However,
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.
45 In fact,
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,
49 and
50 the <TT>getop</TT> routine in the calculator example
51 in section 4.3
52 returned both a code for an operator
53 and a string representing the full text of the operator.
54 (We needed
55 that string
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
61 in these examples.
62 (We'll explore the relationship between arrays and pointers,
63 which made this possible,
64 in section 5.3.)
65 </p><p>With all of this in mind,
66 make sure that you understand why the swap example on page 95
67 would not work,
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>)
73 in its caller.
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.
78 (There
79 is no fundamental difference,
80 though,
81 between
82 ``modifying a variable in the caller''
83 and
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,
89 that is,
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.)
94 To see more clearly
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.
99 In that case,
100 we might use the following simpler
101 (i.e. more primitive)
102 code:
103 <pre> int getint(int *pn)
105 char line[20];
106 if (getline(line, 20) &lt;= 0)
107 return EOF;
108 *pn = atoi(line);
109 return 1;
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,
115 and as it happens,
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>&amp;</TT> need not be restricted to single, simple variables;
123 it can take the address of any data object,
124 in this case,
125 one cell of the <TT>array</TT>.
126 Just as for all of C's other operators,
127 <TT>&amp;</TT> can be applied to arbitrary expressions,
128 although it is restricted to expressions which represent
129 addressable objects.
130 Expressions like
131 <TT>&amp;1</TT> or <TT>&amp;(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.
144 That is,
145 code like
146 <pre> int a = 1, b = 2;
147 swap(&amp;a, &amp;b);
148 </pre>and
149 <pre> int a;
150 getint(&amp;a);
151 </pre>is correct and quite safe.
152 </p><p>Something to beware of,
153 though,
154 is the temptation to inadvertently pass an uninitialized pointer variable
155 (rather than the ``address'' of some other
156 variable)
157 to a routine which expects a pointer.
158 We know that the <TT>getint</TT> routine expects
159 as its argument
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,
162 and wrote
163 <pre> int *ip; /* a pointer to an int */
164 getint(ip);
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>&amp;</TT> operator:
173 <pre> getint(&amp;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>&amp;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,
184 is something like
185 <pre> int a;
186 getint(&amp;a);
187 </pre>In this case,
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>&amp;a</TT>)
191 and call <TT>getint</TT>,
192 <TT>getint</TT> receives a pointer that does point somewhere.
193 </p><hr>
195 Read sequentially:
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>
200 </p>
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>
205 </p>
206 </body>
207 </html>