Thread View: comp.lang.c.moderated
9 messages
9 total messages
Started by Lloyd Hopkins
Mon, 01 Apr 1996 13:20
Pointers to functions
Author: Lloyd Hopkins
Date: Mon, 01 Apr 1996 13:20
Date: Mon, 01 Apr 1996 13:20
15 lines
1227 bytes
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
Author: Konrad Schwarz
Date: Tue, 02 Apr 1996 01:55
Date: Tue, 02 Apr 1996 01:55
82 lines
4520 bytes
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
Author: Lloyd Hopkins
Date: Wed, 03 Apr 1996 13:10
Date: Wed, 03 Apr 1996 13:10
33 lines
1896 bytes
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
Author: Jason A. Farque'
Date: Thu, 04 Apr 1996 00:56
Date: Thu, 04 Apr 1996 00:56
82 lines
3973 bytes
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
Author: Miguel Carrasquer Vidal
Date: Thu, 04 Apr 1996 01:08
Date: Thu, 04 Apr 1996 01:08
76 lines
3553 bytes
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
Author: Herman Rubin
Date: Thu, 04 Apr 1996 01:10
Date: Thu, 04 Apr 1996 01:10
20 lines
1441 bytes
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
Author: Andreas Schwab
Date: Fri, 05 Apr 1996 00:29
Date: Fri, 05 Apr 1996 00:29
24 lines
1427 bytes
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
Author: Richard A. O'Keefe
Date: Fri, 05 Apr 1996 00:50
Date: Fri, 05 Apr 1996 00:50
31 lines
1527 bytes
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
Author: Lloyd Hopkins
Date: Tue, 09 Apr 1996 22:41
Date: Tue, 09 Apr 1996 22:41
13 lines
1057 bytes
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