pointer

B

Bill Cunningham

What is the purpose of this kind of versatility in C? I guess I am
wondering what you would use this syntax for:

int func(int i);
int (*fp) (int i);
fp=func;
fp(1);
func(1);

The last two lines say the same thing. What's the added pointer versatility
for?

Bill
 
K

Keith Thompson

Bill Cunningham said:
What is the purpose of this kind of versatility in C? I guess I am
wondering what you would use this syntax for:

int func(int i);
int (*fp) (int i);
fp=func;
fp(1);
func(1);

The last two lines say the same thing. What's the added pointer versatility
for?

The expression appearing before the '(' in a function call is always
of pointer-to-function type.

An expression of function type (such as the name of a function), in
most contexts, is implicitly converted to a pointer to the function.
(This is similar to what happens to array expressions.)

So the common way of calling a named function:

func(arguments)

is really just a special case of:

function_pointer_expression(arguments)
 
B

Ben Bacarisse

Bill Cunningham said:
What is the purpose of this kind of versatility in C? I guess I am
wondering what you would use this syntax for:

int func(int i);
int (*fp) (int i);
fp=func;
fp(1);
func(1);

The last two lines say the same thing. What's the added pointer versatility
for?

It allows you (amongst other things) to write code that calls a
function without knowing that function by name. To take an example
that is not too far from some of the programs you are writing:

#include <stdio.h>
#include <math.h>

typedef double BinaryFunction(double, double);

double reduce(int size, double *vals, double ival, BinaryFunction *f)
{
double r = ival;
for (int i = 0; i < size; i++)
r = f(r, vals);
return r;
}

double sum(double x, double y) { return x + y; }
double product(double x, double y) { return x * y; }

int main(void)
{
double t[] = { 2, 3, 5, 7, 9 };
int tn = sizeof t / sizeof t[0];
printf("Max: %g\n", reduce(tn, t, NAN, fmax));
printf("Min: %g\n", reduce(tn, t, NAN, fmin));
printf("Arithmetic mean: %g\n", reduce(tn, t, 0, sum)/tn);
printf("Geometric mean: %g\n", pow(reduce(tn, t, 1, product), 1.0/tn));
return 0;
}

Note: C99 code -- compile (if you can) with the right flags.
 
B

bert

    What is the purpose of this kind of versatility in C? I guess I am
wondering what you would use this syntax for:

int func(int i);
int (*fp) (int i);
fp=func;
fp(1);
func(1);

The last two lines say the same thing. What's the added pointer versatility
for?

Further to Ben Bacarisse's excellent post, you
can initialise an array of function pointers,
then select one by indexing and call it, without
"knowing" which of a whole family of functions you
are actually calling. But of course, because you
have computed the index correctly, you know that
whichever one it is, it must be the CORRECT one...

There are types of applications generally describable
as "table-driven code" which lend themselves perfectly
to this sort of implementation technique.
--
 
B

Ben Bacarisse

There are types of applications generally describable
as "table-driven code" which lend themselves perfectly
to this sort of implementation technique.

.... and while we are at it... The other common usage is when an
action needs to be specified (often called a hook or a call-back).
Two standard use cases being 'atexit' and 'signal'.
 
F

Fred

... and while we are at it...  The other common usage is when an
action needs to be specified (often called a hook or a call-back).
Two standard use cases being 'atexit' and 'signal'.

And suppose I want to sort an array of strings.
I might have several different sorting methods
(i.e., ABC...abc... versus AaBbCc..., or reverse sort, etc),
all of which have the same signature.
Then I just change the pointer to point to the function
I want the to use for sorting, then later on I invoke the sort
via the function pointer.

The same idea can be used to compute an integral, or
some other mathematical operation,
using my choice of any one of several different methods.
 
K

Keith Thompson

Ben Bacarisse said:
... and while we are at it... The other common usage is when an
action needs to be specified (often called a hook or a call-back).
Two standard use cases being 'atexit' and 'signal'.

Two others being qsort and bsearch.
 
B

Ben Bacarisse

Keith Thompson said:
Two others being qsort and bsearch.

Its interesting (to me) that I consider that an example like my first
post -- passing a function to determine the computation to be done --
so I did not add it as another example of a call-back but, of course,
it is just such a thing.
 
B

Ben Pfaff

Keith Thompson said:
Two others being qsort and bsearch.

Personally I consider all four of these interfaces flawed because
they do not allow for any reasonable way to pass auxiliary data
to the callback functions. (I don't consider variables declared
at file scope to be reasonable in this context.)
 
S

Stefan Ram

Newsgroups: comp.lang.c,comp.lang.java.programmer
Followup-To: comp.lang.java.programmer

Ben Pfaff said:
Personally I consider all four of these interfaces flawed because
they do not allow for any reasonable way to pass auxiliary data
to the callback functions. (I don't consider variables declared
at file scope to be reasonable in this context.)

This is one place, where Java programming really shines.

In Java, you can't pass a call-back method to another method
at all, you can only pass a call-back object. So, say you
have a call

void qsort( base, nmemb, size, compar );

, then »compar« must be an object, and qsort will call its
»compare« method.

Now, what has this to do with auxiliary data?

An object has to be constructed, like

compar = new Compar( ... );

, and there, at the ellipsis "...", you can put whatever
auxiliary data you can dream of into your compar object.
No need for qsort to be aware of it, no means for qsort
to get in the way of this.

And this might be one reason against a certain kind
of closures in Java.

As soon as a method accepts a closure and in the case that
this is implemented in a way where a closure is a kind of
method, but /not/ a fully fledged object, this way to pass
auxiliary data won't work anymore.

Newsgroups: comp.lang.c,comp.lang.java.programmer
Followup-To: comp.lang.java.programmer
 
B

Bill Cunningham

Ben Bacarisse said:
It allows you (amongst other things) to write code that calls a
function without knowing that function by name.

[snip]

Ok but in my example I used fp=func. I knew the name of the function I
wanted to point to. Did I not use the function pointer concept as deeply as
I could've?

Bill
 
K

Keith Thompson

Bill Cunningham said:
Ben Bacarisse said:
It allows you (amongst other things) to write code that calls a
function without knowing that function by name.

[snip]

Ok but in my example I used fp=func. I knew the name of the function I
wanted to point to. Did I not use the function pointer concept as deeply as
I could've?

Right. Storing the address of a single known function in a pointer,
and then calling via the pointer, demonstrates what function pointers
are, but not how they can be useful.

For example, if you wanted to demostrate what a variable is, you might
write:

int x = 42;
printf("x = %d\n", x);

But this simple example doesn't show why variables are useful. You
could do exactly the same thing like this:

printf("x = %d\n", 42);

or even like this:

puts("x = 42");

Similarly, this:

#include <stdio.h>
void func(void)
{
puts("func");
}
int main(void)
{
void (*fp)(void) = func;
fp();
return 0;
}

demonstrates a trivial use of a function pointer, but not why function
pointers are useful. The declaration and use of fp could have been
replaced with

func();

or even

puts("func");

Function pointers (other than the implicit function pointer that
occurs in every function call) don't become useful until you start
doing more sophisticated things with them.

But very often, to understand a concept, you have to start with
unrealistically trivial examples before moving on to more complex and
realistic cases.
 
B

Barry Schwarz

Ben Bacarisse said:
It allows you (amongst other things) to write code that calls a
function without knowing that function by name.

[snip]

Ok but in my example I used fp=func. I knew the name of the function I
wanted to point to. Did I not use the function pointer concept as deeply as
I could've?

The expression func is a constant. Whenever you use it, it will
always refer to the same function. The object fp is a variable. You
can assign it different values. When you use fp to call a function,
the function that is called depends completely on the last value
assigned to fp.

Now you can file this for future reference but ignore it till you get
a much better understanding of the basics.
 
D

Default User

Barry Schwarz wrote:

Now you can file this for future reference but ignore it till you get
a much better understanding of the basics.

That's optimistic.




Brian
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,677
Members
48,796
Latest member
Greg L.

Latest Threads

Top