Function Pointers

9 views
Skip to first unread message

norid...@gmail.com

unread,
Jun 28, 2006, 5:40:56 PM6/28/06
to
What is the purpose of the function pointer? Why do you need a pointer
to a function. I cannot really think of any application where this is
the only or even easiest solution to a problem. I'm sure there are
really good aplications for it I just cannot think of any, so if anyone
can tell me why a pointer to a function is nessisary and when it
can/should be used I would apreciate that. Thanks.
Nori

Andrew Poelstra

unread,
Jun 28, 2006, 5:50:22 PM6/28/06
to

Arrays of functions can be useful for menus, etc. Or, when writing
a bytecode interpreter:

func[bytecode[i]]();

--
Andrew Poelstra < http://www.wpsoftware.net/blog >
To email me, use "apoelstra" at the above address.
I know that area of town like the back of my head.

Default User

unread,
Jun 28, 2006, 5:53:17 PM6/28/06
to
norid...@gmail.com wrote:


See qsort().


Brian

Jack Klein

unread,
Jun 28, 2006, 5:55:01 PM6/28/06
to
On 28 Jun 2006 14:40:56 -0700, "norid...@gmail.com"
<norid...@gmail.com> wrote in comp.lang.c:

The purpose of a pointer to a function is to hold the address of a
function, and quite possibly to call that function via the pointer.

Open your C book or reference and read about the standard library
functions qsort() and bsearch(). They are also useful in many other
types of coding.

As for whether you ever need function pointers, that depends on the
type of code you write, and also whether you ever intend to use the
standard qsort() or bsearch() functions.

If you don't want to use function pointers, you don't have to,
provided that you don't call any standard or third party library
functions that need them.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html

Frederick Gotham

unread,
Jun 28, 2006, 6:11:09 PM6/28/06
to
norid...@gmail.com posted:


I've always thought Microsoft's "EnumWindows" was a good example.

Here's some sample code:


#include <stdio.h>
#include <stdlib.h>

void ComputePrimeNumbers( void (*Callback)(unsigned long) )
{
Callback(1);

unsigned long i;

unsigned long num = 3;

do
{
for( i = 2 ; ; )
{
if ( !(num % i) ) break;

if ( ++i == num )
{
Callback(num);
break;
}
}

} while ( ++num );
}

void Print( unsigned long const num )
{
printf( "%lu\n", num );
}

#include <cstdlib>

int main(void)
{
ComputePrimeNumbers( Print );

system("PAUSE");
}


--

Frederick Gotham

Frederick Gotham

unread,
Jun 28, 2006, 6:15:57 PM6/28/06
to
Frederick Gotham posted:


> Here's some sample code:

Wups... I'll try that again:

#include <stdio.h>
#include <stdlib.h>

void ComputePrimeNumbers( void (*Callback)(unsigned long) )
{

unsigned long i;

unsigned long num = 3;

Callback(1);

do
{
for( i = 2 ; ; )
{
if ( !(num % i) ) break;

if ( ++i == num )
{
Callback(num);
break;
}
}

} while ( ++num );
}

void Print( unsigned long const num )
{
printf( "%lu\n", num );
}

int main(void)
{
ComputePrimeNumbers( Print );

system("PAUSE");

return 0;
}

--

Frederick Gotham

Richard Heathfield

unread,
Jun 28, 2006, 6:19:18 PM6/28/06
to
Frederick Gotham said:

<snip>

[...listing of code ends with...]



> #include <cstdlib>
>
> int main(void)
> {
> ComputePrimeNumbers( Print );
>
> system("PAUSE");
> }

foo.c:33: cstdlib: No such file or directory


--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)

Richard Heathfield

unread,
Jun 28, 2006, 6:24:08 PM6/28/06
to
Frederick Gotham said:

> Frederick Gotham posted:
>
>
>> Here's some sample code:
>
> Wups... I'll try that again:
>
> #include <stdio.h>
> #include <stdlib.h>
>
> void ComputePrimeNumbers( void (*Callback)(unsigned long) )
> {
> unsigned long i;
>
> unsigned long num = 3;
>
> Callback(1);

1 is not prime.

<snip>
>
> system("PAUSE");

sh: PAUSE: command not found

Was that what you intended?

Charles Richmond

unread,
Jun 28, 2006, 7:06:05 PM6/28/06
to
Fortunately, your lack of imagination does *not* constrain the C
standard in any way... ;-)


--
+----------------------------------------------------------------+
| Charles and Francis Richmond richmond at plano dot net |
+----------------------------------------------------------------+

Tom Plunket

unread,
Jun 28, 2006, 7:29:12 PM6/28/06
to
noridotjabi wrote:

> What is the purpose of the function pointer?

To keep a pointer to a function, of course!

> Why do you need a pointer to a function.

The way I use them mostly is in the implementation of state machines.

For example, in a (modern video-)game you've got a lot of objects
moving around and doing things. Generally each object can go about
its business without worrying about any other object. So, if I store
a function pointer in the object, in the main update loop I don't need
to worry about what the object should be doing... Be sure to catch
the main_game_loop() function at the bottom!

struct GameObject
{
struct GameObject* target;
void (*state)(struct GameObject*);
struct GameObject* next;
}

void eat(struct GameObject* go);
void sleep(struct GameObject* go);

void eat(struct GameObject* go)
{
PlayAnimation(go, "eat");

if (go->target != NULL)
{
/* 1 hit-point of damage to the target per game loop */
ApplyDamage(go->target, 1);
if (IsDead(go->target))
{
/* target will destroy itself in its update */
go->target = NULL;

go->state = sleep;
}
}
}

void sleep(struct GameObject* go)
{
PlayAnimation(go, "sleep")
if (go->target != NULL)
{
/* Uh oh, we've been awakened by an enemy! */
go->state = eat;
}
}

void main_game_loop(void)
{
GameObject* go;

for (go = theGameObjectList; go != NULL; go = go->next)
{
go->state(go);
}
}

I'm sure we can all see how easy game programming is! :)
-tom!

Morris Dovey

unread,
Jun 28, 2006, 7:36:48 PM6/28/06
to
norid...@gmail.com (in
1151530856.9...@75g2000cwc.googlegroups.com) said:

A real world application. A client wanted to describe the internal
behaviors of several lines of appliances using spreadsheets. I wrote
an application to process the spreadsheets and output a binary
pseudo-machine executable for each mode of operation of the described
appliance - as well as the necessary C programs to emulate the
pseudo-machine. This reduced the hand-written code to small
(appliance-specific) device drivers.

The emulator extracted op code and parameters from each p-code
instruction, used the op code as the index into an array of function
pointers, and passed the extracted parameters to the pointed-to
function. The code for the emulator engine was shorter than my
response to you.

This approach to automated control software production allowed a
design engineeer to revise his spread sheet, produce and compile the
uC code, and run a product test in less than an hour - and the
development package could be used for washing machines, dryers,
dishwashers, refrigerators (and more).

It'd have been difficult to do without using a table of function
pointers in the operation dispatcher. :-)

--
Morris Dovey
DeSoto Solar
DeSoto, Iowa USA
http://www.iedu.com/DeSoto


Frederick Gotham

unread,
Jun 28, 2006, 8:44:56 PM6/28/06
to
Richard Heathfield posted:


><snip>
>>
>> system("PAUSE");
>
> sh: PAUSE: command not found
>
> Was that what you intended?


Sorry, not sure what you mean. I tend to put:

system("PAUSE");

at the end of my code snippets because a lot of people use Windows; and on
Windows, a console windows disappears once the program has finished
execution.

It's just for convenience so that my snippets are easy to compile straight-
out-of-the-box.

--

Frederick Gotham

Joshua Shinavier

unread,
Jun 28, 2006, 8:50:35 PM6/28/06
to
norid...@gmail.com wrote:
> What is the purpose of the function pointer? Why do you need a pointer
> to a function.

If C didn't have function pointers, it would be a lot less interesting
IMO. Function pointers give you the means to construct higher-order
functions which deal with things like polymorphism and graph
transformations. GNU C's nested functions are a whole other level of
joy, but these are nonstandard so I won't mention them here :-)

Andrew Poelstra

unread,
Jun 28, 2006, 8:56:56 PM6/28/06
to
On 2006-06-29, Frederick Gotham <fgot...@SPAM.com> wrote:
> Richard Heathfield posted:
>
>
>><snip>
>>>
>>> system("PAUSE");
>>
>> sh: PAUSE: command not found
>>
>> Was that what you intended?
>
>
> Sorry, not sure what you mean. I tend to put:
>
> system("PAUSE");
>
> at the end of my code snippets because a lot of people use Windows; and on
> Windows, a console windows disappears once the program has finished
> execution.
>

I went onto my Windows box and ran a few programs. None of them closed the
console when they were done.

> It's just for convenience so that my snippets are easy to compile straight-
> out-of-the-box.
>

Considering that the Standard says pretty much nothing about what system() does,
I'm not sure how calling it would change how easy it is to compile something.

--
Andrew Poelstra <http://www.wpsoftware.net/blog>
To email me, use "apoelstra" at the above address.

"You people hate mathematics." -- James Harris

ab

unread,
Jun 28, 2006, 9:12:51 PM6/28/06
to
oops,that's C++,
in c, you should be this:
#include <stdlib.h>
int main(void)
{
..............................
return 0; /* or exit(0); */
}

Richard Heathfield 写道:

William Ahern

unread,
Jun 28, 2006, 9:00:14 PM6/28/06
to

I think what he meant was, what if this happened:

sh: PAUSE: destroying orbital craft

Alas, such a scenario likely won't come to pass. But here in comp.lang.c,
we console ourselves with the conviction it's not entirely impossible.

Keith Thompson

unread,
Jun 28, 2006, 9:21:50 PM6/28/06
to

It doesn't affect ease of compilation. It might make them run in a
friendlier manner on Windows, but it's likely to cause an error
message similar to the one above on any other platform -- unless there
happens to be a "PAUSE" command, in which case it will do whatever
nasty thing that command happens to do.

There *should* be an easy way to execute a simple C program and see
its output. If Windows makes that difficult, that difficulty, or
system-specific workarounds for it, shouldn't be imposed on the rest
of us. (And of course you can always open a window and run the
program from the command line, or use whatever function your IDE
provides to run a program and see its output.)

But if you must cater to this Windows bug, there is a portable way to
do it: replace
system("PAUSE");
with
getchar();

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.

Richard Heathfield

unread,
Jun 28, 2006, 9:23:10 PM6/28/06
to
Frederick Gotham said:

> Richard Heathfield posted:
>
>
>><snip>
>>>
>>> system("PAUSE");
>>
>> sh: PAUSE: command not found
>>
>> Was that what you intended?
>
>
> Sorry, not sure what you mean. I tend to put:
>
> system("PAUSE");
>
> at the end of my code snippets because a lot of people use Windows;

True enough, but a lot of people don't use Windows, too, and on such systems
the PAUSE command may not exist, or may not do what you were hoping it did.

> and on Windows, a console windows disappears once the program has
> finished execution.

Not if you're running the program from within a console, it doesn't. And the
best way to run a console program is from within a console.

> It's just for convenience so that my snippets are easy to compile
> straight- out-of-the-box.

Oh, I have no issue with the compilation aspect. It's just the runtime
semantics I'm concerned about.

Frederick Gotham

unread,
Jun 28, 2006, 9:26:55 PM6/28/06
to
Keith Thompson posted:


>> It's just for convenience so that my snippets are easy to compile
>> straight- out-of-the-box.
>
> It doesn't affect ease of compilation.


I meant something more like:

easy to compile and execute straight-out-of-the-box.


> It might make them run in a
> friendlier manner on Windows, but it's likely to cause an error
> message similar to the one above on any other platform -- unless there
> happens to be a "PAUSE" command, in which case it will do whatever
> nasty thing that command happens to do.
>
> There *should* be an easy way to execute a simple C program and see
> its output. If Windows makes that difficult, that difficulty, or
> system-specific workarounds for it, shouldn't be imposed on the rest
> of us. (And of course you can always open a window and run the
> program from the command line, or use whatever function your IDE
> provides to run a program and see its output.)


Acknowledged. I suppose I'll just twiddle my OS settings to make the
console app's stay visible upon termination, and hope that others do the
same.


--

Frederick Gotham

Richard Heathfield

unread,
Jun 28, 2006, 9:48:27 PM6/28/06
to
Keith Thompson said:

<snip>


>
> But if you must cater to this Windows bug, there is a portable way to
> do it: replace
> system("PAUSE");
> with
> getchar();

What a gerharsterly idea.

This whole thing is only really a problem if people launch console
applications via, say, Windows Explorer, instead of opening a console in
which to run the program.

Perhaps it would be wiser simply to add a console session to the Windows
startup sequence, which is easily done. Simply copy the Command Prompt
shortcut from the Accessories submenu to the Startup submenu. The details
of this are of course off-topic here, but no doubt a Windows support
newsgroup would be able to help (and really, it's extremely simple!).

pete

unread,
Jun 28, 2006, 11:04:45 PM6/28/06
to
Andrew Poelstra wrote:
>
> On 2006-06-29, Frederick Gotham <fgot...@SPAM.com> wrote:
> > Richard Heathfield posted:
> >
> >
> >><snip>
> >>>
> >>> system("PAUSE");
> >>
> >> sh: PAUSE: command not found
> >>
> >> Was that what you intended?
> >
> >
> > Sorry, not sure what you mean.

"PAUSE" is not a portable system command.
In other words, it won't work on all systems.
The code you post here, should not be undefined.
Learnig how best to write portable or correct code,
is pretty much the whole point of reading this newgroup.

N869
3. Terms and definitions
3.18
[#1] undefined behavior
behavior, upon use of a nonportable or erroneous program
construct, of erroneous data, or of indeterminately valued
objects, for which this International Standard imposes no
requirements

4. Conformance
[#3] A program that is correct in all other aspects,
operating on correct data, containing unspecified behavior
shall be a correct program and act in accordance with
5.1.2.3.

> > I tend to put:
> >
> > system("PAUSE");
> >
> > at the end of my code snippets because
> > a lot of people use Windows; and on Windows,
> > a console windows disappears once the program has finished
> > execution.

Seriously, is it out of consideration for others,
and not because of a problem that you have?

> >
>
> I went onto my Windows box and ran a few programs.
> None of them closed the
> console when they were done.

It doesn't happen on my windows box
when I open a command prompt window either.
It happened when I ran a program directly from MSVC
by clicking on an icon that looks like a red exclamation mark,
but I don't do that anymore.



> > It's just for convenience so
> > that my snippets are easy to compile straight-
> > out-of-the-box.

No. That's not the reason.
It doesn't make the code easier to compile.

>
> Considering that the Standard says pretty much nothing
> about what system() does,
> I'm not sure how calling it would change
> how easy it is to compile something.

--
pete

lovecreatesbeauty

unread,
Jun 29, 2006, 12:02:00 PM6/29/06
to

norid...@gmail.com wrote:
> What is the purpose of the function pointer? Why do you need a pointer
> to a function.

A function pointer is used to pass a function without firing it. A
pointer provides an alternative way to access an object or a function.

> I cannot really think of any application where this is
> the only or even easiest solution to a problem.

A more complex example with function pointers is the function:

#include <signal.h>
void (*signal(int sig, void (*func)(int)))(int);

lovecreatesbeauty

Kenneth Brody

unread,
Jun 29, 2006, 10:42:11 AM6/29/06
to
Frederick Gotham wrote:
>
> Richard Heathfield posted:
>
> ><snip>
> >>
> >> system("PAUSE");
> >
> > sh: PAUSE: command not found
> >
> > Was that what you intended?
>
> Sorry, not sure what you mean.

He meant that your system() call caused the above error to appear on
his screen when he ran your program.

> I tend to put:
>
> system("PAUSE");
>
> at the end of my code snippets because a lot of people use Windows;

Perhaps, but that's irrelevent in clc.

> and on
> Windows, a console windows disappears once the program has finished
> execution.

Not for me, and I've been running Windows on some of my computers
since version 1.0 was in Alpha testing.

For example:

C:\temp>hello
Hello, world.

C:\temp>

Looks like my window is still there.

Even if running the program from within my IDE, I get a "press any
key to continue" prompt before the window closes.

> It's just for convenience so that my snippets are easy to compile
> straight-out-of-the-box.

I don't see how it helps to compile it. It may, on your system,
help you run it without the window disappearing. However, it only
hurts those not on Windows.

Why not simply add:

while ( getchar() != '\n' ) ;

Or:

printf("Press Enter to continue.\n");
fflush(stdout);
while ( getchar() != '\n' )
;

These will work on non-Windows platforms as well.

Of course, on most systems, the above code will simply annoy the user,
as they wonder "why do I need to press Enter to get this program to
exit?"

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:ThisIsA...@gmail.com>


Richard Heathfield

unread,
Jun 29, 2006, 1:29:22 PM6/29/06
to
Kenneth Brody said:

<snip>

> Of course, on most systems, the above code will simply annoy the user,
> as they wonder "why do I need to press Enter to get this program to
> exit?"

Ctrl-Alt-Del to begin, Start to finish, and now Enter to exit. Got to love
Windows.

Frederick Gotham

unread,
Jun 29, 2006, 1:29:14 PM6/29/06
to
lovecreatesbeauty posted:


> A more complex example with function pointers is the function:
>
> #include <signal.h>
> void (*signal(int sig, void (*func)(int)))(int);


I like the hardcore method ; )

/* Hardcore method */

void (*signal_hardcore(int, void (*p)(int)))(int)
{
return p;
}


/* Dumbed-down method */

typedef void (*Ptr_FuncTakeIntReturnVoid)(int);

Ptr_FuncTakeIntReturnVoid signal_dumb( int, Ptr_FuncTakeIntReturnVoid p )
{
return p;
}


/* Both used the same way */

void Func(int) {}

int main(void)
{
signal_dumb( 0, Func );

signal_hardcore( 0, Func );
}


--

Frederick Gotham

Ben C

unread,
Jun 29, 2006, 1:18:13 PM6/29/06
to
On 2006-06-28, norid...@gmail.com <norid...@gmail.com> wrote:

They're often useful when you have complicated data structures that you
want to iterate through. You write the function that finds its way
through the data structure once, and it calls a callback for each item
inside.

Something like this:

typedef int (*callback_t)(const struct record *record, void *handle);
extern int database_foreach(const struct database *db, callback_t cb);

Because database_foreach calls back whatever I pass in cb, I can use it
for all kinds of things without worrying how things are actually
arranged in the database and how to retrieve them. That code is written
once in database_foreach, and hidden away.

A common way to do this without callbacks, on the other hand, is
something like this:

extern db_iterator *database_start(const struct database *db);
extern const struct record *database_next(const struct database *db,
db_iterator *it);

Here the database code stores everything it needs to know about where it
got to and how to continue the iteration in *it, some kind of object it
creates specially to store this state in. In practice the contents of
*it will be the same sorts of things as are in the stack frame of
database_foreach.

On the other hand if you use database_foreach, the "handle" it calls
back the callback with will in many cases point to an object storing
state for whatever's going on "at the other end".

These are sometimes described as ways to "simulate coroutines in C". You
often find function pointers used in this kind of coroutine situation--
two or more operations which each need their own state and which work
together.

Clever Monkey

unread,
Jun 29, 2006, 1:37:53 PM6/29/06
to
norid...@gmail.com wrote:
> What is the purpose of the function pointer? Why do you need a pointer
> to a function. I cannot really think of any application where this is
> the only or even easiest solution to a problem. I'm sure there are
> really good aplications for it I just cannot think of any, so if anyone
> can tell me why a pointer to a function is nessisary and when it
> can/should be used I would apreciate that. Thanks.
> Nori
>
[Disclaimer: I'm no wizard, but I have been handed a pile of decades-old
C code to maintain. I do what I can with what I have!]

We use function pointers in a few places to implement callbacks. This
allows a variety of calling contexts to run code that can "call back" to
that context to update the UI, get input, read properties &etc.

All without the called code having to know who is calling it.

In this specific case we have a sort of API call that can update the UI
to handle exceptional cases requiring interaction (e.g., "Are you sure
you want to destroy Orbital Death Lasers? (y/N)"), regardless of what
sort of UI that is. Add a UI/interface and all you have to do is change
the code you set the function pointer to -- you do not have to change
code that *other* UIs and interfaces may rely on.

Another use is when implementing a classic data structure like a map or
list. It is common enough for for the sort, search or compare functions
one needs for the data structure to be implemented as a pointer to a
function. This is a similar use to the standard qsort().

Frederick Gotham

unread,
Jun 29, 2006, 2:22:15 PM6/29/06
to
Frederick Gotham posted:


> I like the hardcore method ; )


Who's up for role play? I have an idea for a game!

You've to come up with as complicated a function signature as you can,
but... you also have to devise a story in order to justify its complexity.


OK I'm first!


How about some sort of "runtime-programmable calculator".

All of its operations can be performed using simple functions which all
have the same signature, e.g.:

int Add(int,int);
int Subtract(int,int);
int Divide(int,int);

The calculator must be supplied at runtime with 16 such functions.

The programmable calculator queries a database looking for these 16
operations, and receives a pointer to a 16-element-array of pointers to
functions. (It returns a pointer to an array of definite size rather than a
pointer to the first element of an arrary in order to emphasize that the
array's length must be 16.). Furthermore, in the same query, you must
supply the database with a callback function which it should invoke before
and after it goes checking the database, to indicate its current status.
The callback funtion should have the following signature:

void Indicate(int);


Okay here's what I've got:


/* Let's start off with an actual function */

#include <stdio.h>

int Addition(int const a, int const b)
{
int result = a + b;

printf( "The addition of %i and %i yields: %i\n", a, b, result );

return result;
}


/* Here's the callback function which gets invoked to
inform us of the database's current status. */

void Indicate(int) {}


/* Here's the function which accesses the database and retrieves
our mathematical operations as pointers to functions. */

int (*(*RetrieveOperations(void(*pCallback)(int)))[16])(int,int)
{
pCallback(0);

static int (*array[16])(int,int) =
{ Addition, Addition, Addition, Addition, Addition, Addition,
Addition, Addition, Addition, Addition, Addition, Addition,
Addition, Addition, Addition, Addition };

pCallback(1);

return &array;
}


int main(void)
{
int (*(*p_array)[16])(int,int) = RetrieveOperations(Indicate);


/* Now let's call a few functions */


(*p_array)[0](1,2);
(*p_array)[4](3,4);
(*p_array)[9](5,6);
(*p_array)[12](7,8);
}


Looking forward to reading others' contributions : )


--

Frederick Gotham

Kenneth Brody

unread,
Jun 29, 2006, 2:57:30 PM6/29/06
to
Frederick Gotham wrote:
>
> Frederick Gotham posted:
>
> > I like the hardcore method ; )
>
> Who's up for role play? I have an idea for a game!
>
> You've to come up with as complicated a function signature as you can,
> but... you also have to devise a story in order to justify its complexity.
>
> OK I'm first!
>
> How about some sort of "runtime-programmable calculator".
[...]
> int (*(*RetrieveOperations(void(*pCallback)(int)))[16])(int,int)
[...]

You forgot to mention that there are 4 modes of this calculator,
and therefore it needs to return an array of 4 pointers to these
16-element arrays.

Ready... Go!

Is it possible to declare a function which returns a struct*, with
the struct definition within the prototype?

For example, rather than the 16-element array of pointers to your
handler functions, each array element is a struct consisting of a
pointer to an int version of the function, and to a double version
of the function.

Roberto Waltman

unread,
Jun 29, 2006, 3:10:36 PM6/29/06
to
<norid...@gmail.com> wrote:

>What is the purpose of the function pointer? Why do you need a pointer
>to a function. I cannot really think of any application where this is
>the only or even easiest solution to a problem.

Others already provided good answers. I thought a simple example would
complement them. A common use of function pointers is in table driven
command interpreters.
Let's say you need to write a CD player that is controlled by typing
commands such as "start", "next", etc.
The following could be the core of that program. Should be self
explanatory.

=================================

#include <stdio.h>
#include <string.h>

#define GOOD 1
#define BAD 0

void f_start (void);
void f_stop (void);
void f_pause (void);
void f_resume(void);
void f_next (void);
void f_prev (void);


struct cmd_row
{
char *cmd; /* command name */
char *help; /* command description */
void (*func)(void);/* function to call */
};


struct cmd_row cmd_table[] =
{
{"start", "start playback", f_start },
{"stop", "stop playback", f_stop },
{"pause", "pause playback", f_pause },
{"resume", "resume playback",f_resume},
{"next", "next track", f_next },
{"prev", "previous track", f_prev },
{NULL, NULL, NULL }
};


int cmd_run(char *cmd)
{
struct cmd_row *row = cmd_table;

if (!cmd)
{
return BAD;
}

while (row->cmd)
{
if (!strcmp(cmd, row->cmd))
{
puts(row->help);
(row->func)();
return GOOD;
}
row++;
}
return BAD;
}

=================================

Frederick Gotham

unread,
Jun 29, 2006, 3:55:11 PM6/29/06
to
Kenneth Brody posted:

>> How about some sort of "runtime-programmable calculator".
> [...]
>> int (*(*RetrieveOperations(void(*pCallback)(int)))[16])(int,int)
> [...]
>
> You forgot to mention that there are 4 modes of this calculator,
> and therefore it needs to return an array of 4 pointers to these
> 16-element arrays.

Of course, how negligent of me! Please accept my sincerest apologies.
Here's the updated code as requested ; )


/* Let's start off with an actual function */

#include <stdio.h>

int Addition(int const a, int const b)
{
int result = a + b;

printf( "The addition of %i and %i yields: %i\n", a, b, result );

return result;
}


/* Here's the callback function which gets invoked to
inform us of the database's current status. */


void Indicate(int) {}


/* Here's the function which accesses the database and retrieves
our mathematical operations as pointers to functions. */


int (*(*RetrieveOperations(void(*pCallback)(int)))[16])(int,int)
{
pCallback(0);

static int (*array[16])(int,int) =
{ Addition, Addition, Addition, Addition, Addition, Addition,
Addition, Addition, Addition, Addition, Addition, Addition,
Addition, Addition, Addition, Addition };

pCallback(1);

return &array;
}


/* Here's the function which retrieves four modes. */


int (*(*(*RetrieveFourModes(void(*pCallback)(int)))[4])[16])(int,int)
{
static int (*(*array[4])[16])(int,int);

*array = RetrieveOperations( Indicate );
array[1] = RetrieveOperations( Indicate );
array[2] = RetrieveOperations( Indicate );
array[3] = RetrieveOperations( Indicate );

return &array;
}

int main(void)
{
int (*(*(*p_array)[4])[16])(int,int) = RetrieveFourModes(Indicate);


/* Now let's call a few functions */


(*((*p_array)[0]))[15](1,2);
(*((*p_array)[1]))[14](7,3);
(*((*p_array)[2]))[13](55,8);
(*((*p_array)[3]))[12](1045,87);
}

--

Frederick Gotham

Ben C

unread,
Jun 29, 2006, 5:28:47 PM6/29/06
to

This is a good example also of "data driven programming"-- try writing
this program without the function pointers and you probably end up with
a lot of conditions or switch statements.

I've seen some programs in which switch statements got really out of
hand. Use of function pointer tables is often an option for tidying them
up.

It's probably more efficient too:

If you write:

switch (state)
{
case SOMETHING:
do_something();
...
break
case BLAHBLAH:
do_something_else();
...
break
case ...

... lots and lots more case statements ...

the compiled program has to test the value of state against SOMETHING,
BLAHBLAH, and all the other labels, until it finds a match. If there are
a lot of labels this can be significant-- it is effectively a linear
search for the bit of code to execute. I suppose there's nothing
stopping the compiler building some sort of index for switch statements
with large numbers of cases, although I don't know if they do.

If you use:

fn = functions[state];
(*fn)();

on the other hand, fn is looked up at once by using state as an index.

Al Balmer

unread,
Jun 29, 2006, 6:30:44 PM6/29/06
to
On 29 Jun 2006 21:28:47 GMT, Ben C <spam...@spam.eggs> wrote:

>the compiled program has to test the value of state against SOMETHING,
>BLAHBLAH, and all the other labels, until it finds a match. If there are
>a lot of labels this can be significant-- it is effectively a linear
>search for the bit of code to execute. I suppose there's nothing
>stopping the compiler building some sort of index for switch statements
>with large numbers of cases, although I don't know if they do.
>

They do :-) In fact, they can be downright clever about it, especially
when the case values are non-contiguous.

>If you use:
>
> fn = functions[state];
> (*fn)();
>
>on the other hand, fn is looked up at once by using state as an index.

Works well if the range of state values isn't too great. If they're
non-contiguous, you can set missing ones to NULL and test before
calling.

The best part is that generally the code becomes easier to read.

--
Al Balmer
Sun City, AZ

Tom Plunket

unread,
Jun 29, 2006, 9:15:12 PM6/29/06
to
Ben C wrote:

> This is a good example also of "data driven programming"-- try writing
> this program without the function pointers and you probably end up with
> a lot of conditions or switch statements.

I'd call it "table-oriented programming," if I wasn't afraid of
invoking TopMind. Maybe he doesn't hang out here though...

Building tables of homogenous data is incredibly useful, IMHO. Keeping
the data separate from the code is very important, and table-oriented
programming facilitates a large class of problems relating to that.

-tom!

Barry Schwarz

unread,
Jun 29, 2006, 9:44:37 PM6/29/06
to
On Thu, 29 Jun 2006 17:29:22 +0000, Richard Heathfield
<inv...@invalid.invalid> wrote:

>Kenneth Brody said:
>
><snip>
>
>> Of course, on most systems, the above code will simply annoy the user,
>> as they wonder "why do I need to press Enter to get this program to
>> exit?"
>
>Ctrl-Alt-Del to begin, Start to finish, and now Enter to exit. Got to love
>Windows.

Unix isn't much better. The rename command is mv; the block
read/write command is dd, and one edit command is vi.


Remove del for email

Andrew Poelstra

unread,
Jun 30, 2006, 1:27:00 AM6/30/06
to

Those aren't counter-intuitive. Renaming a file is essentially giving it
a different address. A change-of-address is usually a MoVe. And if you
don't want to use a line editor, try the VIsual editor.

I can't justify dd, other than to say that it's a very powerful tool,
and can be used for more that "Block Reader/Writer" would encompass.

Ian Collins

unread,
Jun 30, 2006, 1:50:39 AM6/30/06
to
Andrew Poelstra wrote:
> On 2006-06-30, Barry Schwarz <schw...@doezl.net> wrote:
>
>>On Thu, 29 Jun 2006 17:29:22 +0000, Richard Heathfield
>><inv...@invalid.invalid> wrote:
>>
>>
>>>Kenneth Brody said:
>>>
>>><snip>
>>>
>>>>Of course, on most systems, the above code will simply annoy the user,
>>>>as they wonder "why do I need to press Enter to get this program to
>>>>exit?"
>>>
>>>Ctrl-Alt-Del to begin, Start to finish, and now Enter to exit. Got to love
>>>Windows.
>>
>>Unix isn't much better. The rename command is mv; the block
>>read/write command is dd, and one edit command is vi.
>>
>
>
> Those aren't counter-intuitive. Renaming a file is essentially giving it
> a different address. A change-of-address is usually a MoVe. And if you
> don't want to use a line editor, try the VIsual editor.
>
The commands are probably this verbose because there were more than 26,
so two characters had to be used :)

--
Ian Collins.

Richard Bos

unread,
Jun 30, 2006, 5:10:05 AM6/30/06
to
Andrew Poelstra <apoe...@localhost.localdomain> wrote:

> On 2006-06-30, Barry Schwarz <schw...@doezl.net> wrote:
> > On Thu, 29 Jun 2006 17:29:22 +0000, Richard Heathfield
> ><inv...@invalid.invalid> wrote:
> >
> >>Kenneth Brody said:
> >>
> >>> Of course, on most systems, the above code will simply annoy the user,
> >>> as they wonder "why do I need to press Enter to get this program to
> >>> exit?"
> >>
> >>Ctrl-Alt-Del to begin, Start to finish, and now Enter to exit. Got to love
> >>Windows.
> >
> > Unix isn't much better. The rename command is mv; the block
> > read/write command is dd, and one edit command is vi.
>
> Those aren't counter-intuitive. Renaming a file is essentially giving it
> a different address.

No, it's giving it a different name. AFAIAA, the inode doesn't even
change.

> A change-of-address is usually a MoVe.

True, but irrelevant to renaming. If I remove the slice of pine saying
"Dunroamin" in a brush letter from my house, and put in its place a
faux-stone plaque saying "RLB MANSION" in faux-chiseled quadrata, I do
not need to pack up the plates.

> And if you don't want to use a line editor, try the VIsual editor.

I'd rather use a real editor, but that's another issue.

Richard

Kenneth Brody

unread,
Jun 30, 2006, 10:52:17 AM6/30/06
to
Richard Bos wrote:
>
> Andrew Poelstra <apoe...@localhost.localdomain> wrote:
>
> > On 2006-06-30, Barry Schwarz <schw...@doezl.net> wrote:
> > > On Thu, 29 Jun 2006 17:29:22 +0000, Richard Heathfield
> > ><inv...@invalid.invalid> wrote:
[...]

> > >>Ctrl-Alt-Del to begin, Start to finish, and now Enter to exit. Got to love
> > >>Windows.
> > >
> > > Unix isn't much better. The rename command is mv; the block
> > > read/write command is dd, and one edit command is vi.
> >
> > Those aren't counter-intuitive. Renaming a file is essentially giving it
> > a different address.
>
> No, it's giving it a different name. AFAIAA, the inode doesn't even
> change.

It does if you move it to a different filesystem.

> > A change-of-address is usually a MoVe.
>
> True, but irrelevant to renaming. If I remove the slice of pine saying
> "Dunroamin" in a brush letter from my house, and put in its place a
> faux-stone plaque saying "RLB MANSION" in faux-chiseled quadrata, I do
> not need to pack up the plates.

However, it's still a "move", and not a "rename" program. Yes, you
can move it to a new name in the same directory, which is the same
effect as a rename, but that's just coincidental.

> > And if you don't want to use a line editor, try the VIsual editor.
>
> I'd rather use a real editor, but that's another issue.

I forget if it was here or elsewhere, but I saw someone point out
(related to the recent "6/6/6" date) that "vi vi vi" is "the editor
of the beast".

Andrew Poelstra

unread,
Jun 30, 2006, 1:04:18 PM6/30/06
to
On 2006-06-30, Richard Bos <r...@hoekstra-uitgeverij.nl> wrote:
> Andrew Poelstra <apoe...@localhost.localdomain> wrote:
>
>> On 2006-06-30, Barry Schwarz <schw...@doezl.net> wrote:
>> > On Thu, 29 Jun 2006 17:29:22 +0000, Richard Heathfield
>> ><inv...@invalid.invalid> wrote:
>> >
>> >>Kenneth Brody said:
>> >>
>> >>> Of course, on most systems, the above code will simply annoy the user,
>> >>> as they wonder "why do I need to press Enter to get this program to
>> >>> exit?"
>> >>
>> >>Ctrl-Alt-Del to begin, Start to finish, and now Enter to exit. Got to love
>> >>Windows.
>> >
>> > Unix isn't much better. The rename command is mv; the block
>> > read/write command is dd, and one edit command is vi.
>>
>> Those aren't counter-intuitive. Renaming a file is essentially giving it
>> a different address.
>
> No, it's giving it a different name. AFAIAA, the inode doesn't even
> change.
>

If you're sending a letter to someone, you use their address. If you're
sending data to a file, you use its name. You don't use the inode. For
all you care (assuming you aren't a filesystem designer), the inode itself
could be metaphysical, and could be changing position with every heartbeat
of the universe.

(My point is that a filename is more analogous to an address than an inode
is.)

Another justification for mv is that /actually/ moving the file (that is,
to another directory) is just as complex as changing the name; instead,
you edit the inode tables of two directories. This is no more a move than
renaming is.

>> A change-of-address is usually a MoVe.
>
> True, but irrelevant to renaming. If I remove the slice of pine saying
> "Dunroamin" in a brush letter from my house, and put in its place a
> faux-stone plaque saying "RLB MANSION" in faux-chiseled quadrata, I do
> not need to pack up the plates.
>

Unless you are lying, you will indeed need to move that wine from RLB
MANSION. If your guests ask for some RLB, and you give them what clearly
tastes like Dunroamin, they won't be very happy.

>> And if you don't want to use a line editor, try the VIsual editor.
>
> I'd rather use a real editor, but that's another issue.
>

I hope you mean emacs or some other great editor, because I've spent all
day arguing with people promoting the merits of M$ notepad. I personally
like vi, but that's hardly a holy war I want to fight.

Richard Heathfield

unread,
Jun 30, 2006, 1:26:05 PM6/30/06
to
Kenneth Brody said:

<snip>


>
> I forget if it was here or elsewhere, but I saw someone point out
> (related to the recent "6/6/6" date) that "vi vi vi" is "the editor
> of the beast".

Um, 6/6/6 was over two thousand years ago. Recent in geological terms, I'll
grant you.

Walter Roberson

unread,
Jun 30, 2006, 1:32:15 PM6/30/06
to
In article <slrnea9dfu.l...@localhost.localdomain>,

Andrew Poelstra <apoe...@localhost.localdomain> wrote:
>On 2006-06-30, Barry Schwarz <schw...@doezl.net> wrote:
>> On Thu, 29 Jun 2006 17:29:22 +0000, Richard Heathfield
>><inv...@invalid.invalid> wrote:

>> Unix isn't much better. The rename command is mv; the block
>> read/write command is dd, and one edit command is vi.

>I can't justify dd, other than to say that it's a very powerful tool,

dd == "data duplicator" according to some sources. The syntax might
have been modeled on IBM's JCL "DD" statement.

--
Prototypes are supertypes of their clones. -- maplesoft

Joe Wright

unread,
Jun 30, 2006, 2:42:38 PM6/30/06
to
Richard Heathfield wrote:
> Kenneth Brody said:
>
> <snip>
>> I forget if it was here or elsewhere, but I saw someone point out
>> (related to the recent "6/6/6" date) that "vi vi vi" is "the editor
>> of the beast".
>
> Um, 6/6/6 was over two thousand years ago. Recent in geological terms, I'll
> grant you.
>
No smiley? It was 24 days ago. :=)

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---

Richard Heathfield

unread,
Jun 30, 2006, 2:52:00 PM6/30/06
to
Joe Wright said:

> Richard Heathfield wrote:
>> Kenneth Brody said:
>>
>> <snip>
>>> I forget if it was here or elsewhere, but I saw someone point out
>>> (related to the recent "6/6/6" date) that "vi vi vi" is "the editor
>>> of the beast".
>>
>> Um, 6/6/6 was over two thousand years ago. Recent in geological terms,
>> I'll grant you.
>>
> No smiley? It was 24 days ago. :=)

No, it wasn't. 24 days ago, it was 6/6/2006, which is a very different date
indeed.

MY programs did NOT need Y2K mods, and will not need Y2.1K mods either.

Walter Roberson

unread,
Jun 30, 2006, 2:46:08 PM6/30/06
to
In article <evadnZ8jj-w...@bt.com>,
Richard Heathfield <inv...@invalid.invalid> wrote:

>Um, 6/6/6 was over two thousand years ago. Recent in geological terms, I'll
>grant you.

Two thousand years ago, that notation wouldn't have been
used for dates. If you are going to interpret as a date, you need
to use present-day interpretation of what it means, and in present-day
interpretation, there is no real standard that would require that
it be interpreted as anything other than sometime this century.

Now, if ISO date notation had been used...
--
All is vanity. -- Ecclesiastes

Keith Thompson

unread,
Jun 30, 2006, 4:29:51 PM6/30/06
to
robe...@ibd.nrc-cnrc.gc.ca (Walter Roberson) writes:
> In article <evadnZ8jj-w...@bt.com>,
> Richard Heathfield <inv...@invalid.invalid> wrote:
>
>>Um, 6/6/6 was over two thousand years ago. Recent in geological terms, I'll
>>grant you.
>
> Two thousand years ago, that notation wouldn't have been
> used for dates. If you are going to interpret as a date, you need
> to use present-day interpretation of what it means, and in present-day
> interpretation, there is no real standard that would require that
> it be interpreted as anything other than sometime this century.

Sure there is. The order is ambiguous, but it's natural to interpret
the fields of 6/6/6 as the year, month, and date. The year 6 was 2000
years ago (even though it wasn't called that at the time).

There are also common notations in which 6/6/6 would mean June 6, 2006
(or June 6, 1906) -- but 06 is a more likely representation for the
year than just 6. The lack of a leading 0 on the year "6" makes it
more likely that it refers to the year 6 rather than 2006 (or 1996).

> Now, if ISO date notation had been used...

then it would have been even more obvious -- but ISO 8601 does allow
(but not encourage) the year to be represented by its last two digits.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.

Reply all
Reply to author
Forward
0 new messages