Function Pointers

B

bwaichu

I'm struggling with the concept of function pointers. I understand
that a function pointer contains the memory address of the function.
But I'm not sure how they are effectively used, and I'm not 100% sure
on their syntax.

This is a program I wrote to give myself an idea of how to use them.
But I'm not quite getting it. And I'm not sure what the syntax is for
a function pointer with parameters.

#include <stdio.h>

void foo(void (*)());
void foo2(void);

int
main(int argc, char **argv) {

foo(&foo2);
return 0;
}

void
foo(void (*name)()) {

(void)printf("in foo\n");
(name)();
return;
}

void
foo2(void) {
(void)printf("in foo2\n");
return;
}
 
B

Ben Bacarisse

I'm struggling with the concept of function pointers. I understand
that a function pointer contains the memory address of the function.

OK, if that helps to get started but it helps to think more abstractly
as time goes by. [Aside: one system I used compiled each function
into its own memory segment, and these were just numbered. Since
every function started at address 0 of the segment, there was no point
in including that, so function pointers were half the size of other
pointers and they all looked like small integers. If your program had
three functions, they had "address" 0, 1 and 2.]
But I'm not sure how they are effectively used, and I'm not 100% sure
on their syntax.

They are often used "callbacks" -- a vague word that describes a
situation where you need to pass behaviour as a parameter. The
classic case is the comparison function passed to C's qsort.
This is a program I wrote to give myself an idea of how to use them.
But I'm not quite getting it. And I'm not sure what the syntax is for
a function pointer with parameters.

Typedefs really help here. You can typdef the function type to leave
the pointer explicit:

typedef void void_function_no_params(void);

void f(void_function_no_params *function_ptr);
#include <stdio.h>

void foo(void (*)());

better:

void foo(void (*)(void));

or even, for more clarity, add a dummy name:

void foo(void (*f)(void));

If the function being pointer to takes no parameters, put void in the
()s.
void foo2(void);

int
main(int argc, char **argv) {

foo(&foo2);
return 0;
}

void
foo(void (*name)()) {

(void)printf("in foo\n");

The cast is really not helping here. I'd loose it.
(name)();

That looks odd to me, but it is, of course, fine. It does make me
wonder, why stop there? Why not '((name)());'? The brackets don't
help disambiguate a complex expression here so I think it better to
leave them off.
return;
}

void
foo2(void) {
(void)printf("in foo2\n");
return;
}

I'll note, in passing, that I don't usually put a return at the end of
void function. I wonder if other people do?
 
W

Wang Jiaji

I'm struggling with the concept of function pointers. I understand
that a function pointer contains the memory address of the function.
But I'm not sure how they are effectively used, and I'm not 100% sure
on their syntax.

This is a program I wrote to give myself an idea of how to use them.
But I'm not quite getting it. And I'm not sure what the syntax is for
a function pointer with parameters.

In the machine code, the function's pointer and the function's name
are really the same thing, they're both the start point of a block of
instructions. The only difference is that, _in the C code_, you can't
reassign the function name to another block of instructions, while you
can with the function pointer. Unfortunately, your sample code missed
the only purpose of this candy syntax in C :p
 
B

bwaichu

In the machine code, the function's pointer and the function's name
are really the same thing, they're both the start point of a block of
instructions. The only difference is that, _in the C code_, you can't
reassign the function name to another block of instructions, while you
can with the function pointer. Unfortunately, your sample code missed
the only purpose of this candy syntax in C :p

I write assembly, so I'm used to returning out of all functions
(whether I set eax or not on x86 machines), and I am aware of calling
memory locations that contain functions from dlls, rather than
importing them.

But I struggle with practical usage and examples of function
pointers. I want to make sure I am getting the syntax right, and I
would like to know when I should use them. I think, the only place I
have seen them used is in libpcap.

Thanks.
 
V

Vimal Aravindashan

I write assembly, so I'm used to returning out of all functions
(whether I set eax or not on x86 machines), and I am aware of calling
memory locations that contain functions from dlls, rather than
importing them.

But I struggle with practical usage and examples of function
pointers. I want to make sure I am getting the syntax right, and I
would like to know when I should use them. I think, the only place I
have seen them used is in libpcap.
Well, one practical use of function pointers is, as Ben pointed out, its
use as a callback functions. Arrays of function pointers are also
useful. For example, you could have a set of signals:

int rts(void *data);
int cts(void *data);
int txd(void *data);
int rxd(void *data);

a typedef:

typedef int (*fp)(void *data);

an array of function pointers:

fp mysignals[] = {rts, cts, txd, rxd};

and use them as:

int err;
err = mysignals[0](NULL);
err = mysignals[2]((void *)"SOMETHING");

where the signals could be defined as:

int rts(void *data)
{
/* ignore data, do seomthing */
return 0;
}

int txd(void *data)
{
char *buf = (char *)data;
/* do something with buf */
return 0;
}

From what you had posted, I take it that you have got the syntax right.
As for where you should use function pointers, well, that depends a lot
on what you are trying to do.


Regards,
Vi
 
N

Nick Keighley

I'm struggling with the concept of function pointers.  I understand
that a function pointer contains the memory address of the function.
But I'm not sure how they are effectively used, and I'm not 100% sure
on their syntax.

This is a program I wrote to give myself an idea of how to use them.
But I'm not quite getting it.  And I'm not sure what the syntax is for
a function pointer with parameters.
#include <stdio.h>

void foo(void (*)());

the syntax is messy. So I tend to hide behind typedefs

typedef void (*Func_ptr) (void);
void foo (Func_ptr fp);


and the typedef for a func ptr with a parameters:-

typedef int (*Param_func_ptr) (int);
void foo2(void);

int
main(int argc, char **argv) {

        foo(&foo2);

or even
foo (foo2);

        return 0;

}

void
foo(void (*name)()) {

void foo (Func_ptr name)
{
        (void)printf("in foo\n");

what's the void cast for?
        (name)();

what are the brackets for?
        return;

}

void
foo2(void) {
        (void)printf("in foo2\n");
        return;

I also prefer to omit all those forward declarations...

#include <stdio.h>

typedef void (*Func_ptr) (void);

void foo (Func_ptr name)
{
printf ("in foo\n");
name ();
}

void foo2(void)
{
printf ("in foo2\n");
}

int main(int argc, char **argv)
{
foo (&foo2);
return 0;
}


uses of function pointers? Call backs and jump tables.
see qsort() in the standard library.
 
R

Richard Heathfield

Vimal Aravindashan said:

int txd(void *data)
{
char *buf = (char *)data;

Just a heads-up - you don't need the cast. Conversion from void * (and
indeed to void *) is automatic[1]:

char *buf = data;


[1] Since the subject is function pointers, it's probably as well to point
out that the Standard doesn't require implementations to provide a
lossless conversion between void * and function pointers, cast or no cast.

For a generic function pointer type, use something like int (*)(void), and
use an explicit cast when required - one of the very few good uses for a
cast.
 
V

vippstar

Vimal Aravindashan said:

int txd(void *data)
{
char *buf = (char *)data;

Just a heads-up - you don't need the cast. Conversion from void * (and
indeed to void *) is automatic[1]:

char *buf = data;

[1] Since the subject is function pointers, it's probably as well to point
out that the Standard doesn't require implementations to provide a
lossless conversion between void * and function pointers, cast or no cast.

For a generic function pointer type, use something like int (*)(void), and
use an explicit cast when required - one of the very few good uses for a
cast.
Can you do that without invoking some sort of undefined behavior?
If you can, why int (*)(void) and not void (*)(void) or some other
type?
I thought you couldn't have a generic function pointer like the 'void
*' pointer.
 
R

Richard Heathfield

(e-mail address removed) said:
Can you do that without invoking some sort of undefined behavior?
Yes.

If you can, why int (*)(void) and not void (*)(void) or some other
type?

void (*)(void) works too. Any function pointer type works, as long as you
cast the assignment.
I thought you couldn't have a generic function pointer like the 'void
*' pointer.

You don't get the automatic implicit conversion, so a cast is required. But
any function pointer type can be converted to any other function pointer
type and back, without loss of information.

I *know* this to be true, but I'm struggling to find the bit of the
Standard that says so. Any offers, anyone?
 
K

Keith Thompson

Vimal Aravindashan said:
int txd(void *data)
{
char *buf = (char *)data;

Just a heads-up - you don't need the cast. Conversion from void * (and
indeed to void *) is automatic[1]:

char *buf = data;

[1] Since the subject is function pointers, it's probably as well to point
out that the Standard doesn't require implementations to provide a
lossless conversion between void * and function pointers, cast or no cast.

For a generic function pointer type, use something like int (*)(void), and
use an explicit cast when required - one of the very few good uses for a
cast.
Can you do that without invoking some sort of undefined behavior?
If you can, why int (*)(void) and not void (*)(void) or some other
type?
I thought you couldn't have a generic function pointer like the 'void
*' pointer.

In one sense, there is no generic function pointer type. In another
sense, you can treat *any* function pointer type as generic.

void* is a generic object pointer type (well, object or incomplete
pointer type) in two different senses. One is that you can convert a
value of any pointer-to-object-or-incomplete type to void* and back
again, and you're guaranteed to get back the original value. The
other is that such conversions may be done implicitly, without a cast
(this is due to the legality rules for simple assignment, which also
apply to initialization and argument passing).

For function pointers, you can convert a value from any
pointer-to-function type to any other pointer-to-function type and
back again, and you're guaranteed to get back the original value. (In
that sense, all pointer-to-function types act like void*). But *none*
of these conversions can be done implicitly; they all require a cast
(unless you're converting from a type to the same type).

But if you try to use a converted function pointer without converting
it back to its original type, the behavior is undefined. Don't do
that.

The answer to your question "why int (*)(void) and not void (*)(void)"
is that there's no good reason; either will work equally well.
Personally, I find that void (*)(void) "feels" a bit more generic, but
it's the same kind of dispute as which key you should press in
response to a "Press any key" prompt; it doesn't matter as long as you
don't hit the reset key.

If you feel the need for a generic pointer-to-function type, you
should probably create a typedef for it.
 
B

bwaichu

If you feel the need for a generic pointer-to-function type, you
should probably create a typedef for it.

Can you walk me through the typedef'ing of a function pointer? I'm
not clear on the syntax, and the examples posted early confuse me. Is
the purpose of the typedef to make the code more readable?

Thanks.
 
K

Keith Thompson

Richard Heathfield said:
(e-mail address removed) said: [...]
I thought you couldn't have a generic function pointer like the 'void
*' pointer.

You don't get the automatic implicit conversion, so a cast is required. But
any function pointer type can be converted to any other function pointer
type and back, without loss of information.

I *know* this to be true, but I'm struggling to find the bit of the
Standard that says so. Any offers, anyone?

C99 6.3.2.3p8, in the "Conversions" section. Quoting from n1256 (no
change bars on that paragraph):

A pointer to a function of one type may be converted to a pointer
to a function of another type and back again; the result shall
compare equal to the original pointer. If a converted pointer is
used to call a function whose type is not compatible with the
pointed-to type, the behavior is undefined.

(It should be similar or identical in C89/C90.)
 
V

vippstar

Can you walk me through the typedef'ing of a function pointer? I'm
not clear on the syntax, and the examples posted early confuse me. Is
the purpose of the typedef to make the code more readable?
Here's an example
-- snip.c --
#include <stdio.h>

typedef void (*generic_fptr)(void);
typedef int (*puts_ptr)(const char *); /* int puts(const char *) */

int main(void) {
generic_fptr foo = (generic_fptr)puts;
puts_ptr bar;

bar = (puts_ptr)foo;
bar("Hello, World");
return 0;
}
-- snip.c --
 
V

vippstar

Vimal Aravindashan said:
<snip>
int txd(void *data)
{
char *buf = (char *)data;
Just a heads-up - you don't need the cast. Conversion from void * (and
indeed to void *) is automatic[1]:
char *buf = data;
[1] Since the subject is function pointers, it's probably as well to point
out that the Standard doesn't require implementations to provide a
lossless conversion between void * and function pointers, cast or no cast.
For a generic function pointer type, use something like int (*)(void), and
use an explicit cast when required - one of the very few good uses for a
cast.
Can you do that without invoking some sort of undefined behavior?
If you can, why int (*)(void) and not void (*)(void) or some other
type?
I thought you couldn't have a generic function pointer like the 'void
*' pointer.
If you feel the need for a generic pointer-to-function type, you
should probably create a typedef for it.
Thanks for your response, that's what I had in mind (about the typedef)
 
F

Flash Gordon

Richard Heathfield wrote, On 21/01/08 18:42:

You don't get the automatic implicit conversion, so a cast is required. But
any function pointer type can be converted to any other function pointer
type and back, without loss of information.

I *know* this to be true, but I'm struggling to find the bit of the
Standard that says so. Any offers, anyone?

In N1256 it is section 6.3.2.3 paragraph 8.
| A pointer to a function of one type may be converted to a pointer to a
| function of another type and back again; the result shall compare
| equal to the original pointer. If a converted pointer is used to call
| a function whose type is not compatible with the pointed-to type,
| the behavior is undeï¬ned.
 
K

Keith Thompson

Can you walk me through the typedef'ing of a function pointer? I'm
not clear on the syntax, and the examples posted early confuse me. Is
the purpose of the typedef to make the code more readable?

I can't right now; I'll post another followup tonight if nobody else
gets to it.
 
G

gw7rib

I'm struggling with the concept of function pointers.  I understand
that a function pointer contains the memory address of the function.
But I'm not sure how they are effectively used, and I'm not 100% sure
on their syntax.

There's one detail that may be confusing you, which is that you are
allowed to leave off the "&" if you want to.

Normally, if you say, for example:

int a;

then "a" and "&a" are different things. The first is of type int, and
contains the value of a, which will normally be stored in a memory
location somewhere. The second is of type pointer to int, and
identifies the memory location in which a is stored.

But, in the following case:
#include <stdio.h>

void foo(void (*)());
void foo2(void);

int
main(int argc, char **argv) {

        foo(&foo2);

You can use the & if you want to, and it may make you happy, as foo2
is a function and so &foo2 is a pointer to function. But foo2 doesn't
have a "value" as such, and so if you write:

foo(foo2);

the compiler will realise that what you want is a pointer to foo2, and
will treat it exactly the same as above.

Hope this helps - other people have commented on other details.
Paul.
 
R

Richard Heathfield

Keith Thompson said:
Richard Heathfield said:
(e-mail address removed) said: [...]
I thought you couldn't have a generic function pointer like the 'void
*' pointer.

You don't get the automatic implicit conversion, so a cast is required.
But any function pointer type can be converted to any other function
pointer type and back, without loss of information.

I *know* this to be true, but I'm struggling to find the bit of the
Standard that says so. Any offers, anyone?

C99 6.3.2.3p8, in the "Conversions" section. Quoting from n1256 (no
change bars on that paragraph):

A pointer to a function of one type may be converted to a pointer

Aha! Thank you.

[...]
(It should be similar or identical in C89/C90.)

Now that I know what to look for, it's easy to find (duh!). In C89, it's in
3.3.4.
 
R

Richard Heathfield

(e-mail address removed) said:
Can you walk me through the typedef'ing of a function pointer? I'm
not clear on the syntax, and the examples posted early confuse me. Is
the purpose of the typedef to make the code more readable?

Others have shown you how to typedef a function pointer type. My own take
is that it's better not to do this, because I don't like hiding pointers
in typedefs. So I would typedef the function type itself:

typedef int myfunctiontype(int, char **);

and then I'd define a pointer to it using a good old out-in-the-open *,
like this:

myfunctiontype *entrypoint = main;

(It's true that myfunctiontype foo; is an error because you can't create
objects of function type, but the answer to that is easy: Don't Do That.)

I accept that this way may not be everybody's slice of apple pie. Style is
often a matter of taste.
 
D

dj3vande

Richard Heathfield said:
Others have shown you how to typedef a function pointer type. My own take
is that it's better not to do this, because I don't like hiding pointers
in typedefs. So I would typedef the function type itself:
[...]

I accept that this way may not be everybody's slice of apple pie. Style is
often a matter of taste.

Pointers to functions are fundamentally different from pointers to
object types in many ways (among others, they can't be inter-converted
(with other function pointers implicitly, or with object pointers at
all), and you can't change the function a function pointer points at,
while you can (modulo constness) change the object an object pointer
points at).

Because of these differences, my own stylistic preference on typedefing
pointers differs between the two types; hiding the pointer-ness of
object pointers behind a typedef is Evil, but hiding the pointer-ness
of function pointers behind a typedef is no worse than typedefing the
function while leaving the pointer-ness exposed.
(Note that in either case, the typedef hides the argument list of the
function, which is often what you're interested in when you're using
the pointer. For that reason I generally prefer to write my function
pointer types without typedefs until they start getting unwieldy enough
for the loss of clutter from the typedefs to be worth the loss of
information.)


dave
(prefers good cherry pie over apple, but apple over most others)

--
Dave Vandervies dj3vande at eskimo dot com
Subject: Justify the output in the program
You could use nroff.
--kaushalgoa and Ben Pfaff in comp.lang.c
 

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
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top