* remove "\r" nonsense
[mascara-docs.git] / C / the.ansi.c.programming.language / c.programming.notes.int / sx10a.html
blob238b2e225bf0da45aa68ab8a3a0df5b6d3a9269c
1 <!DOCTYPE HTML PUBLIC "-//W3O//DTD W3 HTML 2.0//EN">
2 <!-- This collection of hypertext pages is Copyright 1995-7 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>24.1 Declaring, Assigning, and Using Function Pointers</title>
10 <link href="sx10.html" rev=precedes>
11 <link href="sx10b.html" rel=precedes>
12 <link href="sx10.html" rev=subdocument>
13 </head>
14 <body>
15 <H2>24.1 Declaring, Assigning, and Using Function Pointers</H2>
17 <p>Just as for data pointers,
18 we can think of three steps involved in using function pointers.
19 First,
20 we must declare a variable which can hold a pointer to a function,
21 and this ends up being a somewhat complex declaration.
22 A simple function pointer declaration looks like this:
23 <pre>
24 int (*pfi)();
25 </pre>
26 This declares <TT>pfi</TT> as a
27 pointer to a function which will return an <TT>int</TT>.
28 As in other declarations,
29 the <TT>*</TT> indicates that a pointer is involved,
30 and the parentheses <TT>()</TT> indicate that a function is involved.
31 But what about the extra parentheses around <TT>(*pfi)</TT>?
32 They're needed because there are precedence relationships
33 in declarations just as there are in expressions,
34 and when the default precedence doesn't give you what you want,
35 you have to override it with explicit parentheses.
36 In declarations,
37 the <TT>()</TT> indicating functions
38 and the <TT>[]</TT> indicating arrays
39 ``bind'' more tightly than
40 the <TT>*</TT>'s indicating pointers.
41 Without the extra parentheses, the declaration above would look like
42 <pre>
43 int *pfi(); /* WRONG, for pointer-to-function */
44 </pre>
45 and this would declare a function returning a pointer to <TT>int</TT>.
46 With the explicit parentheses, however,
47 <TT>int (*pfi)()
48 </TT>tells us that <TT>pfi</TT> is a pointer first,
49 and that what it's a pointer to is a function,
50 and what that function returns is an <TT>int</TT>.
51 </p><p>It's common to use typedefs
52 (see
54 section 18.1.6)
55 with complicated types such as function pointers.
56 For example,
57 after defining
58 <pre>
59 typedef int (*funcptr)();
60 </pre>
61 the identifier <TT>funcptr</TT> is now a synonym
62 for the type ``pointer to function returning int''.
63 This typedef would make
64 declaring pointers such as <TT>pfi</TT> considerably easier:
65 <pre>
66 funcptr pfi;
67 </pre>
68 (In
70 section 18.1.6,
71 we mentioned that typedefs were a little bit like preprocessor
72 <TT>define</TT> directives, but better.
73 Here we see another
74 reason:
75 there's no way we could define a preprocessor macro which would
76 expand to a correct function pointer declaration,
77 but the <TT>funcptr</TT> type we just defined using <TT>typedef</TT>
78 will work just fine.)
79 </p><p>Once declared,
80 a function pointer can of course be set to point to some function.
81 If we declare some functions:
82 <pre>
83 extern int f1();
84 extern int f2();
85 extern int f3();
86 </pre>
87 then we can set our pointer <TT>pfi</TT> to point to one of them:
88 <pre>
89 pfi = &amp;f1;
90 </pre>
91 or to one or another of them depending on some condition:
92 <pre>
93 if(condition)
94 pfi = &amp;f2;
95 else pfi = &amp;f3;
96 </pre>
97 (Of course, we're not restricted to these two forms;
98 we can assign function pointers under any circumstances we wish.
99 The second example could be rendered more compactly
100 using the conditional operator:
101 <TT>pfi = condition ? &amp;f2 : &amp;f3</TT> .)
102 </p><p>In these examples, we've used the <TT>&amp;</TT> operator
103 as we always have,
104 to generate a pointer.
105 However, when generating pointers to functions,
106 the <TT>&amp;</TT> is optional,
107 because when you mention the name of a function but are not calling it,
108 there's nothing else you could possibly be trying to do except
109 generate a pointer to it.
110 So, most programmers write
111 <pre>
112 pfi = f1;
113 </pre>
115 <pre>
116 if(condition)
117 pfi = f2;
118 else pfi = f3;
119 </pre>
120 (or, equivalently,
121 using the conditional operator,
122 <TT>pfi = condition ? f2 : f3</TT> ).
123 </p><p>(The fact that a function pointer is generated automatically
124 when a function appears in an expression but is not being called
125 is very similar to, and in fact related to,
126 the fact that a pointer to the first element of an array
127 is generated automatically when an array appears in an expression.)
128 </p><p>Finally,
129 once we have a function pointer variable
130 which does point to a function,
131 we can call the function that it points to.
132 Broken down to a near-microscopic level,
133 this, too,
134 is a three-step procedure.
135 First,
136 we write the name of the function pointer variable:
137 <pre>
139 </pre>
140 This is a pointer to a function.
141 Then, we put the <TT>*</TT> operator in front,
142 to ``take the contents of the pointer'':
143 <pre>
144 *pfi
145 </pre>
146 Now we have a function.
147 Finally, we append an argument list in parentheses,
148 along with an extra set of parentheses to get the precedence right,
149 and we have a function call:
150 <pre>
151 (*pfi)(arg1, arg2)
152 </pre>
153 The extra parentheses are needed here
154 for almost exactly the same reason
155 as they were in the declaration of <TT>pfi</TT>.
156 Without them,
157 we'd have
158 <pre>
159 *pfi(arg1, arg2) /* WRONG, for pointer-to-function */
160 </pre>
161 and this would say,
162 ``call the function <TT>pfi</TT>
163 (which had better return a pointer),
164 passing it the arguments <TT>arg1</TT> and <TT>arg2</TT>,
165 and take the contents of the pointer it returns.''
166 However,
167 what we want to do is take the contents of <TT>pfi</TT>
168 (which is a pointer to a function)
170 call the pointed-to function,
171 passing it the arguments <TT>arg1</TT> and <TT>arg2</TT>.
172 Again, the explicit parentheses override the default precedence,
173 arranging that we apply the <TT>*</TT> operator to <TT>pfi</TT>
174 and <em>then</em> do the function call.
175 </p><p>Just to confuse things,
176 though,
177 parts of the syntax are optional here as well.
178 There's nothing you can do with a function pointer
179 except assign it to another function pointer,
180 compare it to another function pointer,
181 or call the function that it points to.
182 If you write
183 <pre>
184 pfi(arg1, arg2)
185 </pre>
186 it's obvious,
187 based on the parenthesized argument list,
188 that you're trying to call a function,
189 so the compiler goes ahead and calls the pointed to function,
190 just as if you'd written
191 <pre>
192 (*pfi)(arg1, arg2)
193 </pre>
194 When calling the function pointed to by a function pointer,
195 the <TT>*</TT> operator
196 (and hence the extra set of parentheses)
197 is optional.
198 I prefer to use the explicit <TT>*</TT>,
199 because that's the way I learned it
200 and it makes a bit more sense to me that way,
201 but you'll
202 also
203 see code which leaves it
205 out.
206 </p><p></p><hr>
208 Read sequentially:
209 <a href="sx10.html" rev=precedes>prev</a>
210 <a href="sx10b.html" rel=precedes>next</a>
211 <a href="sx10.html" rev=subdocument>up</a>
212 <a href="top.html">top</a>
213 </p>
215 This page by <a href="http://www.eskimo.com/~scs/">Steve Summit</a>
216 // <a href="copyright.html">Copyright</a> 1996-1999
217 // <a href="mailto:scs@eskimo.com">mail feedback</a>
218 </p>
219 </body>
220 </html>