🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.lang.c.moderated
Article #2457

Re: Pointers to functions

#2457
From: Konrad Schwarz
Date: Tue, 02 Apr 1996 01:55
82 lines
4520 bytes
Lloyd Hopkins
> The main thing which is puzzling me, is just why
> you'd want to create a pointer to a function?

A classic example is the general-purpose integration subroutine, which is
supposed to calculate the definite integral (i.e., with explicit
integration bounds) of an arbitrary function.  You'd like a user of your
integration routine to be able to supply her own function to compute
the integrand; an appropriate function signature might be
	r = integ (f, a, b);
so that r is the integral of function f integrated over the interval
[a, b].  To declare f properly in integ, you must declare it as a
function pointer:
	float integ (float (*f) (float), float a, float b)
to evaluate f at point t in integ, use
	f (t)
(You could also say (*f) (t), but C has a special rule so that the
two are equivalent.)

Another nice example was recently posted by Kazimir Kylheku,
subject ``Re: State engine,'' message id <4jol5l$1qe@solutions.solon.com>,
where you want to call functions through some kind of structure, exemplified
by the line
	statetable[state][input].action();
which calls the ``action'' routine found at the (discrete) coordinates
(state, input).

In fact, much of object-oriented programming languages reduces to having
the compiler do clever things with function pointers.

> Another thing is that looking
> at the sort program in 5.11, there is a reference to a function called
> "comp", but I can't actually see any function called "comp" anywhere in
> the code?

I don't have K&R handy, so I'm guessing---but I wouldn't be surprised if
comp is one of the sort procedure's arguments.  This again would be a
good example (K&R of course :) for a function pointer.  The objective
of the comparision function is probably to sort an array of pointers to
arbitrary ``things.''  Now, the sort routine doesn't know anything about
these ``things''---all it knows is how to sort quickly.  It needs some way of
deciding the sorted order of two ``things,'' and does this by calling the
user specified comp function.  The comp function is the only thing that
needs to know about ``things,'' specifically, it can decide which of two
is the ``bigger'' one.  The code contains no comp function because it must
be supplied by the user of the sort procedure.

The key to complex declarations is knowing that postfix operators, such
as () /* procedure parenthesis */ and [] /* array brackets */ bind tighter
than prefix operators, such as * /* pointer */.  Both types of operators
bind from the ``inside out,'' meaning that the closer an operator is to
the variable's name, the earlier it is considered in type determination.
However, postfix operators still bind tighter than prefix operators, no
matter how far away they are, i.e., postfix operators get considered earlier
during type determination.

The standard way to override precedence is to use parenthesis and this rule
applies to prefix and postfix operators as well.  If you want a prefix operator
to bind tighter than a postfix operator, enclose the subexpression starting
with the prefix operator up to but not including the postfix operator in
parenthesis.  Thus, to get a pointer to an array of 10 integers, use
	int (*p) [10];
if you don't use the parenthesis, you get
	int  *p [10];
which is a array of 10 pointers to integers.

This looks more confusing with functions, since you need parenthesis
just to indicate that the thing is a function:
	int f ();
declares f to be a function that returns an integer.  (It also happens
to be a bad coding style, since it uses an ``old-style'' declaration that says
nothing about f's arguments, but that is a different topic.)  Now,
	int *f ();
declares f to be a function returning a pointer to an integer; if you want
a pointer to a function returning an integer, write
	int (*f) ();

As it turns out, C is such that you can omit the variable name in any
declaration and still exactly know what the type is being declared; this is
useful in certain situations.

Konrad Schwarz
Technical Details
Message-ID: <4jq1ef$a2u@solutions.solon.com>
Path: arc1-ca.pugleaf.net!solon.com!not-for-mail
References: <4jol6u$1sn@solutions.solon.com>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!solon.com!not-for-mail
From: schwarz@mips.complang.tuwien.ac.at (Konrad Schwarz)
Newsgroups: comp.lang.c.moderated
Subject: Re: Pointers to functions
Date: 1 Apr 1996 19:55:27 -0600
Organization: Vienna University of Technology, Austria
Sender: clc@solutions.solon.com
Approved: clc@solutions.solon.com
Message-ID: <4jq1ef$a2u@solutions.solon.com>
References: <4jol6u$1sn@solutions.solon.com>
NNTP-Posting-Host: solutions.solon.com