🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: comp.lang.c.moderated
9 messages
9 total messages Started by Lloyd Hopkins Mon, 01 Apr 1996 13:20
Pointers to functions
#2451
Author: Lloyd Hopkins
Date: Mon, 01 Apr 1996 13:20
15 lines
1227 bytes
Hi,

I've recently been working my way through K&R (second edition) and whilst
most of it is clear enough, I'm having trouble with 5.11, 5.12 (Pointers to
Functions, Complicated Declarations) and I thought I'd ask here to see
if anyone can help.  The main thing which is puzzling me, is just why
you'd want to create a pointer to a function?  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'd also appreciate it if anyone could direct me to any more
sources of information on the topics covered in 5.11 and 5.12.

Thanks in advance for any help,

Lloyd
Re: Pointers to functions
#2457
Author: 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
Re: Pointers to functions
#2473
Author: Lloyd Hopkins
Date: Wed, 03 Apr 1996 13:10
33 lines
1896 bytes
In article <4jq1ef$a2u@solutions.solon.com>
           schwarz@mips.complang.tuwien.ac.at "Konrad Schwarz" writes:

> 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

Yes, that was what I was referring to.  After reading the replies I got to
my query, it all made sense :)

> The key to complex declarations is knowing that postfix operators, such
> as () /* procedure parenthesis */ and [] /* array brackets */ bind tighter

I am having some difficulty with some of the examples in 5.12.  The first
few are straight forward enough, but (for example):

char (*(*x[3])())[5]

is pretty confusing to figure!  I'll print out your advice and take a look
at it again.

Thanks very much for the help, it's much appreciated.  

By the way, it's possible that I might not have seen some replies to the 
newsgroup as my feed seems to be losing the odd message.  Well, I never 
saw my original posting on the local server anyway.  Apologies to anyone
who followed up to this group and didn't receive a reply.

Thanks again,
Lloyd

-- 
Lloyd Hopkins                Email : lloyd@bomber.demon.co.uk
                             WWW   : http://www.netlink.co.uk/users/lloyd 
Re: Pointers to functions
#2487
Author: Jason A. Farque'
Date: Thu, 04 Apr 1996 00:56
82 lines
3973 bytes
On 1 Apr 1996 07:20:30 -0600, Lloyd Hopkins <Lloyd@bomber.demon.co.uk>
wrote:

>Hi,
>
>I've recently been working my way through K&R (second edition) and whilst
>most of it is clear enough, I'm having trouble with 5.11, 5.12 (Pointers to
>Functions, Complicated Declarations) and I thought I'd ask here to see
>if anyone can help.  The main thing which is puzzling me, is just why
>you'd want to create a pointer to a function?  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'd also appreciate it if anyone could direct me to any more
>sources of information on the topics covered in 5.11 and 5.12.
>
>Thanks in advance for any help,
>
>Lloyd

Lloyd,

I can give you an example of why *I* use pointers to functions.  There
are many different reasons, of course.

As an embedded systems programmer, I'm always writing code to handle
user interfaces of one kind or another.  Often these user interfaces
have an LCD display that has one or two lines of text, a button or
two, etc.  Here's a fairly typical construct of mine...  Comments from
passersby are welcome...

typedef struct {
   char *LineOne;
   char *LineTwo;
   void (* Function)(unsigned char);
}LCDMENUSTRUCT;

LCDMENUSTRUCT LcdMenu[] = {
{ "1: USING GPS?:", "Left button changes", MenuToggleGPS },
{ "2: FILES -> PC", "Left button begins", MenuSendRecordings },
{ "3: YOUR TIMEZONE:", "Left button changes", MenuSetTimeZone },
{ "4: SET CLOCK IN TOOL", "Left button begins", MenuSetClock },
{ "5: BATTERY CAL:", "Left button changes", MenuCalBatteryOffset },
{ "6: BATT LOW AT:", "Left button begins", MenuSetBatteryLevel },
{ "7: SERIAL NUMBER:", "Left button changes", MenuSetSerNum },
{ "8: RESET FILE MEMORY", "Left button begins", MenuRstFileMem },
{ "9: RESTORE DEFAULTS", "Left button begins", MenuSaneSystem }
};

I've stripped out some of the structure members to simplify this
example, but what we've got here is a structure LCDMENUSTRUCT that
contains two pointers to text strings "LineOne" and "LineTwo".  These
are obviously displayed on the LCD display itself...  The third
structure member is a pointer to a function (the function names
themselves).  As the user presses the RIGHT button (there are only
two), I increment an offset number that points into the structure and
redisplay the text.  I increment and check to see if the offset number
goes beyond the end of the stucture with this code:

if( ++MenuOffset > ((sizeof(LcdMenu)/sizeof(LCDMENUSTRUCT))-1) ) {
   MenuOffset = 0;
}

However, if the user presses the LEFT button I make a function call
that looks like this:

   LcdMenu[MenuOffset].Function(DO_CODE);

This makes it very simple for me to add a menu item.  I merely write a
function to do whatever the new menu item is, add a line to the
structure and I'm done.  This allows me to have a fairly small LCD
menu "Engine" function that runs the menu system without modification
no matter how I jack around with the menu items themselves.  For
instance, I can comment out a line or two of the LcdMenu structure and
those items simply "go away".

That's a real-world example...  Hope it helps you understand the
usefullness of pointers to functions...  They're cool.  When you need
'em, you need 'em bad.

Jason A. Farque'
CDI - Worldwide Suppliers of Pipeline Pig Location & Tracking Equipment.
Tulsa, Oklahoma, USA
Re: Pointers to functions
#2490
Author: Miguel Carrasquer Vidal
Date: Thu, 04 Apr 1996 01:08
76 lines
3553 bytes
Lloyd Hopkins <Lloyd@bomber.demon.co.uk> wrote:

>I've recently been working my way through K&R (second edition) and whilst
>most of it is clear enough, I'm having trouble with 5.11, 5.12 (Pointers to
>Functions, Complicated Declarations) and I thought I'd ask here to see
>if anyone can help.  The main thing which is puzzling me, is just why
>you'd want to create a pointer to a function?  

Pointers to functions can be handy for a sorting algorithm, for
instance.  "The sorting algorithm is independent of the comparison
[and exchange] operations, so by passing different comparison [and
exchange] functions to it, we can arrange to sort by different
criteria."  That's pretty clear, I think.

>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?

"comp" is the name of a _pointer_ to a function.  The actual functions
called in this case are "numcmp" or "strcmp"...

The call to qsort (p. 119 in my edition) is:

   qsort((void **)lineptr, 0, nlines-1,
      (int (*)(void *, void *))(numeric ? numcmp : strcmp));

in other words, you pass a _pointer_ to the function "numcmp" or
"strcmp", depending on whether the sort should be numeric or
alphabetic.

Pointers to functions are really not that different from ordinary
variables.  When you declare say "int year", you know that you can
assign "year=1996;" and call "print_year(year);".  "print_year()"
doesn't have to know the value of the "year" variable, and should work
fine given the assignment "year=2000;" (or will it?).

The confusing thing I guess about function-pointer variables is that
you're "catching" a piece of code inside of a data variable, and pass
that around.  While the principle of "given this condition, do this,
otherwise do something else" is at the heart of any computer program
above the level of complexity of "hello, world!", in most cases what
you do is simply:

if(this)
	do_this();
else	do_that();

Pointers to functions allow a different approach.  Not one you need to
use every day, but one which can be very useful in things like
sorting, state machines, or anywhere your code can benefit from the
"added generality" [what I mean is that I can't explain when you
should use it: after a while you just find yourself in a given
situation and you say "I could use a function pointer here", and you
do].  It looks something like this:

void (*somefunction)(void);

if(this)
	somefunction=do_this;
else	somefunction=do_that;

somefunction();

The effect is exactly the same as in the piece of code above that
called do_this() or do_that() directly.  The difference is that you
now have this variable "somefunction" that you can call, assign to,
compare, pass around to another function (like qsort()), etc.


==
Miguel Carrasquer Vidal                     ~ ~
Amsterdam                   _____________  ~ ~
mcv@pi.net                 |_____________|||

========================== Ce .sig n'est pas une .cig
Re: Pointers to functions
#2496
Author: Herman Rubin
Date: Thu, 04 Apr 1996 01:10
20 lines
1441 bytes
In article <4jol6u$1sn@solutions.solon.com>,
Lloyd Hopkins  <Lloyd@bomber.demon.co.uk> wrote:
>Hi,

>I've recently been working my way through K&R (second edition) and whilst
>most of it is clear enough, I'm having trouble with 5.11, 5.12 (Pointers to
>Functions, Complicated Declarations) and I thought I'd ask here to see
>if anyone can help.  The main thing which is puzzling me, is just why
>you'd want to create a pointer to a function?

A good example is where a subroutine uses buffers, which can be
refilled as needed.  The buffer descriptors and the functions
refilling them are unknown to the subroutine at compile time,
and are to be filled in by the main program, or higher subroutine
at run time.  These may also be changed at run time, so the only
locations in the subroutine are pointers to the buffers and
refill functions.
-- 
Herman Rubin, Dept. of Statistics, Purdue Univ., West Lafayette IN47907-1399
hrubin@stat.purdue.edu	 Phone: (317)494-6054	FAX: (317)494-0558
Re: Pointers to functions
#2501
Author: Andreas Schwab
Date: Fri, 05 Apr 1996 00:29
24 lines
1427 bytes
In article <4jttba$3gt@solutions.solon.com>, Lloyd Hopkins <Lloyd@bomber.demon.co.uk> writes:

|> I am having some difficulty with some of the examples in 5.12.  The first
|> few are straight forward enough, but (for example):

|> char (*(*x[3])())[5]

|> is pretty confusing to figure!  I'll print out your advice and take a look
|> at it again.

Take this apart from inside out, and you'll get:

          x		is
	  x[3]		an array of three
	 *x[3]		pointers pointing to
	(*x[3])()	a function (taking an unspecified number of
			arguments) returning
       *(*x[3])()	a pointer to
      (*(*x[3])())[5]	an array of five
 char (*(*x[3])())[5]   characters

-- 
Andreas Schwab                                      "And now for something
schwab@issan.informatik.uni-dortmund.de              completely different"
Re: Pointers to functions
#2517
Author: Richard A. O'Keefe
Date: Fri, 05 Apr 1996 00:50
31 lines
1527 bytes
Lloyd Hopkins <Lloyd@bomber.demon.co.uk> writes:
>I am having some difficulty with some of the examples in 5.12.  The first
>few are straight forward enough, but (for example):

>char (*(*x[3])())[5]

>is pretty confusing to figure!

There is a free program available on the net called "cdecl".

g% cdecl
Type `help' or `?' for help
cdecl> explain char (*(*x[3])())[5]
declare x as array 3 of pointer to
  function returning pointer to array 5 of char
cdecl> quit

It's very useful for reading other people's code.
Weird declarations like that are seldom useful.
More usual would be

    typedef char (*five_char_ptr)[5];
    typedef five_char_ptr (*five_char_function_ptr)();
    five_char_function_ptr x[3];

I can live with two type constructors (*, [], or ()) in a declaration,
but three is a bit too much.

-- 
Result of state election = 50% Victorians didn't get MP of their choice.
Richard A. O'Keefe; http://www.cs.rmit.edu.au/~ok; RMIT Comp.Sci.
Re: Pointers to functions
#2563
Author: Lloyd Hopkins
Date: Tue, 09 Apr 1996 22:41
13 lines
1057 bytes
Hi,

Thanks to everyone who replied.  I thought it would better to just send
one reply to the group, to avoid wasting bandwidth.  Well, thanks to all
the help I got I can now understand the part of the K&R which was causing
trouble and I've got some leads to other reading material too.

Thanks again to everyone who helped.

Lloyd
-- 
Lloyd Hopkins                Email : lloyd@bomber.demon.co.uk
                             WWW   : http://www.netlink.co.uk/users/lloyd 
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads