Function pointer array as parameter to a function

A

aruna.mysore

Hi all,

I have a specific problem passing a function pointer array as a
parameter to a function. I am trying to use a function which takes a
function pointer array as an argument. I am too sure about the syntax
of calling the same.

#include <stdio.h>

void fp1()
{ printf("In fp1\n"); }

void fp2()
{ printf("In fp2\n");}

void fp3()
{ printf("In fp3\n");}

void call_fpn(void (*fp[3])())
{
(*fp[0])();
(*fp[1])();
(*fp[2])();
}

void main()
{
void (*pfn[3])()={NULL};
pfn[0]=&fp1;
pfn[1]=&fp2;
pfn[2]=&fp3;

call_fpn(.....);
}

Can someone please let me know what is the right syntax for calling
the function accepting a function pointer array.

Thanks in advance.
Ar
 
V

vippstar

Hi all,

I have a specific problem passing a function pointer array as a
parameter to a function. I am trying to use a function which takes a
function pointer array as an argument. I am too sure about the syntax
of calling the same.
Can someone please let me know what is the right syntax for calling
the function accepting a function pointer array.


#include <stdio.h>

#define foo() printf("%s\n", __func__)

void f1() { foo(); }
void f2() { foo(); }
void f3() { foo(); }
void doit(void (**f)()) {
size_t i;

for(i = 0; f; f[i++]())
;
}

int main(void) {

void (*f[4])() = {0};

f[0] = f1;
f[1] = f2;
f[2] = f3;

doit(f);

return 0;
}
 
J

Jens Thoms Toerring

I have a specific problem passing a function pointer array as a
parameter to a function. I am trying to use a function which takes a
function pointer array as an argument. I am too sure about the syntax
of calling the same.

You're attempt already looks rather good.
#include <stdio.h>
void fp1()

I think it's better to exactly specify the the types of arguments
(or that no argument is to be expected):

void fp1( void )
{ printf("In fp1\n"); }
void fp2()
{ printf("In fp2\n");}
void fp3()
{ printf("In fp3\n");}
void call_fpn(void (*fp[3])())
{
(*fp[0])();
(*fp[1])();
(*fp[2])();
}

You can simplify that to

void call_fpn( void ( * fp[ 3 ] )( void ) )
{
fp[ 0 ]( );
fp[ 1 ]( );
fp[ 2 ]( );
}

A function pointer followed by parentheses does call the function,
no need to dereference the pointer.

And if you don't want to restrict yourself to an array of
fixed size just use

void call_fpn( void ( ** fp )( void ) )
void main()

main() always returns an int, so make that

int main( void )
{
void (*pfn[3])()={NULL};

You can do the initialization already with the definition:

void ( * pfn[ 3 ] )( void ) = { fp1, fp2, fp3 };
pfn[0]=&fp1;

The name of the function alone is already a pointer to the
function (at least when it's used as a value), so the '&'
isn't necessary.
pfn[1]=&fp2;
pfn[2]=&fp3;
call_fpn(.....);

Just pass 'pfn' as the argument:

call_fpn( pfn );

return 0;
Regards, Jens
 
V

vippstar

I have a specific problem passing a function pointer array as a
parameter to a function. I am trying to use a function which takes a
function pointer array as an argument. I am too sure about the syntax
of calling the same.

You're attempt already looks rather good.
#include <stdio.h>
void fp1()

I think it's better to exactly specify the the types of arguments
(or that no argument is to be expected):

void fp1( void )
{ printf("In fp1\n"); }
void fp2()
{ printf("In fp2\n");}
void fp3()
{ printf("In fp3\n");}
void call_fpn(void (*fp[3])())
{
(*fp[0])();
(*fp[1])();
(*fp[2])();
}

You can simplify that to

void call_fpn( void ( * fp[ 3 ] )( void ) )
{
fp[ 0 ]( );
fp[ 1 ]( );
fp[ 2 ]( );

}

A function pointer followed by parentheses does call the function,
no need to dereference the pointer.

And if you don't want to restrict yourself to an array of
fixed size just use
He isn't. The [3] really is just informative, but actually a pointer.
<snip>
 
J

Jens Thoms Toerring

void call_fpn( void ( * fp[ 3 ] )( void ) )

And if you don't want to restrict yourself to an array of
fixed size just use
He isn't. The [3] really is just informative, but actually a pointer.

Of course, you're right.
Regards, Jens
 
B

Bart

(e-mail address removed) wrote:

You can simplify that to
void call_fpn( void ( * fp[ 3 ] )( void ) )

You seem to be quite good at this:

Consider that parameter type, call it T:

void (*fp[3])void

How could I modify T to end up with an array [N] of T?

How could I modify T to have a pointer to T?

How could I modify T to have a function returning type T?

Please add any parentheses that might be needed.

(I need ask a similar question in a different guise recently. But no
replies, so it was either incredibly difficult, or so trivial that
nobody could understand why I was even asking. I contrived a solution
of sorts but it was unsatisfactory.)

-- Thanks,

Bartc
 
J

Jens Thoms Toerring

Bart said:
(e-mail address removed) wrote:

You can simplify that to
void call_fpn( void ( * fp[ 3 ] )( void ) )
Consider that parameter type, call it T:
void (*fp[3])void

I guess you meant

void (*fp[3])( void )
How could I modify T to end up with an array [N] of T?
How could I modify T to have a pointer to T?
How could I modify T to have a function returning type T?

I am not sure if I understand your questions correctly, so
what I write in the following might be completely off the
mark...

First thing I would consider when things get too complicated
is using a typedef for the type of function pointer passed
around, e.g.

typedef void ( * func_t )( void );

'func_t' is now a new type that is a pointer to a function
which takes no arguments and returns nothing.

Now you can e.g. write the call_fpn() function as

void call_fpn( func_t fp[ 3 ] )

which already looks a lot more readable.

As someone else already has pointed out the '[3]' bit isn't
really relevant, what the function receives is a pointer to
the first element of an array of function pointers. So you
could also write that as

void call_fpn( func_t fp[ ] )

or

void call_fpn( func_t *fp )

If you now want the call_fpn() function to return a function
pointer of the same type as the ones in the array it got
passed then just change it to e.g.

func_t call_fpn( func_t *fp )
{
fp[ 0 ]( );
fp[ 1 ]( );
return fp[ 2 ];
}

Then you can do in main() e.g.

int main( void )
{
funct_t pfn[ 3 ] = { fp1, fp2, fp3 }
call_fpn( pfn )( );
return 0;
}

This will result in fp1() and fp2() getting called from within
call_fpn() and then the function returned by call_fpn(), fp3,
being called from within main().

If you insist on not using a typedef things will look a lot
uglier. E.g. call_fpn() then would have to be defined instead
of

func_t call_fpn( func_t *fp )

as

void ( * call_fpn( void ( ** fp )( void ) ) )( void )

(I hope I got that right, at least the compiler doesn't com-
plain;-) which I find extremely hard to understand...

Does that about answer what you asked? Otherwise please help
me by trying to describe the problem a bit differently.

Regards, Jens
 
K

Keith Thompson

I have a specific problem passing a function pointer array as a
parameter to a function. I am trying to use a function which takes a
function pointer array as an argument. I am too sure about the syntax
of calling the same.
[...]

You can't. In C, a function cannot take an array as a parameter.

It can *appear* to do so:

void func(int arr[]);

...

int my_array[42];
func(my_array);

but in fact the parameter "arr" is just a pointer, and the argument
"my_array" is implicitly *converted* to a pointer (to the first
element of the array) when it's evaluated.

See section 6 of the comp.lang.c FAQ, <http://www.c-faq.com/>.
 
A

aruna.mysore

Hi all,

Thank you everyone for your time and responses.

Thanks and Regards,
Ar
 
B

Bart

Bart said:
(e-mail address removed) wrote:
You can simplify that to
void call_fpn( void ( * fp[ 3 ] )( void ) )
Consider that parameter type, call it T:
void (*fp[3])void

I guess you meant

void (*fp[3])( void )
Yes.
How could I modify T to end up with an array [N] of T?
How could I modify T to have a pointer to T?
How could I modify T to have a function returning type T?

I am not sure if I understand your questions correctly, so
what I write in the following might be completely off the
mark... ...
void ( * call_fpn( void ( ** fp )( void ) ) )( void )

(I hope I got that right, at least the compiler doesn't com-
plain;-) which I find extremely hard to understand...

Does that about answer what you asked? Otherwise please help
me by trying to describe the problem a bit differently.

I find C types incomprehensible other than the simplest.

So I was after a way of simply building up a complex type step by
step, working from an left-to-right description in English. And
starting from a non-trivial type so that I can see how you place any
new stuff in relation to *, [] and ().

Typedefs are also a useful build tool but I think I need to be able
build types out of primary elements first. This is for both straight
coding, and machine-generated code when readability isn't so
important.
 
J

Jens Thoms Toerring

Bart said:
I find C types incomprehensible other than the simplest.

Me too;-) It's actually a lot simpler to me assembling
them then parsing them.
So I was after a way of simply building up a complex type step by
step, working from an left-to-right description in English.

At least in the more complicated cases it isn't left-to-right
but more like zig-zack... KR2 has some subchapter on the topic
(5.12) but that doesn't make it any simpler.
And starting from a non-trivial type so that I can see how you place any
new stuff in relation to *, [] and ().
Typedefs are also a useful build tool but I think I need to be able
build types out of primary elements first. This is for both straight
coding, and machine-generated code when readability isn't so
important.

There's a definitely a logic behind it since e.g. the cdecl program
can deal with such things (and the compiler, of course, also does;-).
If you want to machine-generate code looking at the sources of that
program may give you some ideas (I didn't, so I can't say how well-
written it is).

But when I have to construct something "by hand" I would start
with a typedef and "expand" the typedef. E.g. if you have a
typedef like

typedef void ( * func_t )( void );

and you want to rewrite

func_t call_fpn( func_t *fp )

in basic types I would replace the 'func_t' parts in the following
way

a) take everything from the typedef before the string 'func_t'
(except the 'typedef' keyword, of course) and replace the
occurence of 'func_t' by it.
b) take everything following 'func_t' in the typedef (except the
semicolon) and put it behind the stuff 'func_t' was applied to
(i.e. everything until the next unbalanced closing paranthesis
or the end of the declaration/function signature, whatever comes
first).

So replacing the first 'func_t' that way in

func_t call_fpn( func_t * fp )

using

typedef void ( * func_t )( void );
^^^^^^^^ ^^^^^^^^^
before after

leads to

void ( * call_fpn( func_t * fp ) )( void )
^^^^^^^^ ^^^^^^^^^
before after

That gets rid of the first instance of 'func_t'. The second one
can be replaced the same way:

void ( * call_fpn( void ( * * fp )( void ) ) )( void )
^^^^^^^^ ^^^^^^^^^
before after

I don't know if that helps at all. But perhaps by approaching
the problem from the point of view that typedefs can be "ex-
panded" by textual replacement on the one hand and that you
can simplify complicated declarations with typedefs on the
other, leading to relatively easy to read declarations, gives
you some ideas of how to approach things in your program...

Regards, Jens
 
B

Bart

Me too;-) It's actually a lot simpler to me assembling
them then parsing them.

OK, I've come up with a technique which I think is along the lines you
suggested with typedefs, but was actually derived by trying lots of
things with cdecl!

This works for types that involve a name of some sort (like
declarations, but not casts, although I'd imagine they'd be similar).

* Start with any declaration that has a name, such as int x;

* To create an array N of that, replace the name x by (x[N])

* To create a pointer to that, replace the name by (*x)

* To create a function returning that, replace the name by (x()). (If
it takes parameters, put those inside the ().)

With the capability of stacking these to any extent. However there are
likely superfluous parentheses in there rendering the result, for
complex cases, even more unreadable.

To try this on the OP's problem, he first wanted an Array 3 of Pointer
to Function taking () and returning Void. Hmmm, I think you have to go
right to left with this:

void x

Now add a function returning that:

void (x()) /* already it's clear the outer () not needed) */

Now a pointer to that, following my rules:

void ((*x)())

Finally, an array[3] of that:

void ((*(x[3]))())

And his call_fpn() function I think wanted a pointer to that lot,
namely:

void ((*((*x)[3]))()) /* the 3 not useful here */
 
B

Bart

I've streamlined the processs to construct arbitrary C type
declarations from English, to avoid extra parentheses:

* Start with any declaration that has a name, such as int x;

* To create an array N of that, replace the name x by x[N] or (x[N])

* To create a pointer to that, replace the name x by (*x), although
when x already has * on it's left, the parentheses are not needed.

* To create a function returning that, replace the name x by x() or
(x()). Any parameter types go inside the ().

(Using the same logic in reverse, it's even possible for a human to
actually figure out what a complex declaration does! But really it
shouldn't be necessary to go to all this trouble..)

I'm having trouble however building cast types using this method.

I've tried doing the above using a dummy name, which is then removed
and the whole thing enclosed in parentheses. And I've tried keeping
the original extra parentheses around each extra addition.

But cdecl is temperamental on these and compilers don't generally tell
you the exact meaning of the type; only lccwin spells it out in
English but it doesn't always correspond to what I think.

So what is the normal technique for a type specification to be
converted from declarative form to a cast?
 
N

Nick Keighley

On May 20, 4:10 am, Bart <[email protected]> wrote:
I've streamlined the processs to construct arbitrary C type
declarations from English, to avoid extra parentheses:

* Start with any declaration that has a name, such as int x;

I'm not sure how this helps. Why not start with a bare
identifier? How does your method help with ptr-to-funcs?

* To create an array N of that, replace the name x by x[N] or (x[N])

* To create a pointer to that, replace the name x by (*x), although
when x already has * on it's left, the parentheses are not needed.

int x -> int (*x)

this looks wrong. The easiest way is build them up in stages
using typedefs.

With function ptrs I just remember that

int *f ()
is a function returning int*

and
int (*f)()
is a pointer to a function returning int

I don't do clever things with arrays.

* To create a function returning that, replace the name x by x() or
(x()). Any parameter types go inside the ().

(Using the same logic in reverse, it's even possible for a human to
actually figure out what a complex declaration does! But really it
shouldn't be necessary to go to all this trouble..)

well it becomes necessary if someone insists on using the raw
declaration syntax. Can you decode this one?

void (*signal(int sig, void (*func)(int)))(int);

(assuming I copied it correctly!)

I'm having trouble however building cast types using this method.

cast types? I think the answer is typedefs again.

/* simple case */
j = (int*)n;

/* ptr-to function taking in tand returning void */
typedef void (*FP)(int);

/* takes an FP and returns an FP */
FP func_s (FP);

so if a cast is needed
func_s ((FP)something_else);

I've tried doing the above using a dummy name, which is then removed
and the whole thing enclosed in parentheses. And I've tried keeping
the original extra parentheses around each extra addition.

But cdecl is temperamental on these and compilers don't generally tell
you the exact meaning of the type; only lccwin spells it out in
English but it doesn't always correspond to what I think.

So what is the normal technique for a type specification to be
converted from declarative form to a cast?

use a typedef
 
B

Ben Bacarisse

Bart said:
On May 20, 4:10 am, Bart <[email protected]> wrote:
I'm having trouble however building cast types using this method.

I've tried doing the above using a dummy name, which is then removed
and the whole thing enclosed in parentheses. And I've tried keeping
the original extra parentheses around each extra addition.

But cdecl is temperamental on these and compilers don't generally tell
you the exact meaning of the type; only lccwin spells it out in
English but it doesn't always correspond to what I think.

So what is the normal technique for a type specification to be
converted from declarative form to a cast?

The normal rule is just to write a declaration, remove the name and
the ; and enclose in ()s. Do you have an example where this is wrong?
 
B

Bart

The normal rule is just to write a declaration, remove the name and
the ; and enclose in ()s.  Do you have an example where this is wrong?

Now that I try to find an example, it's not so easy!

Probably there was no actual error, apart from actual errors of syntax
and odd things like this:

int ((*((*(x(char)))[]))[]);
int y;

x = (int ((*((*((char)))[]))[]))y;

This a type error (the type returns a function). But decl was quite
happy with the cast when written without the 'char':

(int ((*((*(()))[]))[]))y

But gave a syntax error on: (int ((*((*((char)))[]))[]))y

So just funny things with cdecl.
 
B

Bart

I'm not sure how this helps. Why not start with a bare
identifier?

Getting started is actually not so easy! Anyway even I can cope with
int x, y[], *z;
How does your method help with ptr-to-funcs?

If int fn(char) is a function decl then int (*fn)(char) is a pointer
to it, according to cdecl and using my (old)rule#2.
* To create an array N of that, replace the name x by x[N] or (x[N])
* To create a pointer to that, replace the name x by (*x), although
when x already has * on it's left, the parentheses are not needed.

int x  ->  int (*x)

this looks wrong. The easiest way is build them up in stages
using typedefs.

I think my methods are wrong. I tested only on terms of types that
were already well-specified with parentheses.

OK, so I'll go back to my original steps and forget about avoiding
parentheses. If the result obviously doesn't need then, as in your
example, then they can be left out.
With function ptrs I just remember that

int *f ()
is a function returning int*

and
int (*f)()
is a pointer to a function returning int

I don't do clever things with arrays.

I meant if the C type system had been done properly!
well it becomes necessary if someone insists on using the raw
declaration syntax. Can you decode this one?

void (*signal(int sig, void (*func)(int)))(int);

No, only if written according to my rules. But I'll have a go. It
looks like:

void (*s()) (int)

Which I would have to have to write as: void (*(s()))(int). By
striking and eliminating from the inside out, I did struggle to the
correct result. The params of s or signal are easy: each one is an
independent type and is decoded by itself.

cast types? I think the answer is typedefs again.

   /* simple case */
   j = (int*)n;

   /* ptr-to function taking in tand returning void */
   typedef void (*FP)(int);

   /* takes an FP and returns an FP */
   FP func_s (FP);

so if a cast is needed
   func_s ((FP)something_else);

void func_s(int) /* step 1, basic type */
void (*func_s)(int) /* step 2, declared ptr-to-fn */
(void (*)(int))x /* step 3, cast */

I just wrote these myself without any help and checked with cdecl!

In practice yes typedefs can be used but I need to understand this
basic stuff first.
 
V

vippstar

Functions, you need to add an extra asterisk (*), ie
int foo(int);
int (*)(int)
Now that I try to find an example, it's not so easy!

Probably there was no actual error, apart from actual errors of syntax
and odd things like this:

int ((*((*(x(char)))[]))[]);
Why the redundant parenthesis?
That's equivalent to int (*(*x(char))[])[], and what the function
returns is a pointer to an incomplete array of pointers to incomplete
arrays of int.
int y;

x = (int ((*((*((char)))[]))[]))y;
x is a function, you cannot assign to it.
This a type error (the type returns a function). But decl was quite
happy with the cast when written without the 'char':

(int ((*((*(()))[]))[]))y

But gave a syntax error on: (int ((*((*((char)))[]))[]))y

So just funny things with cdecl.
It's funny things with your code, nod cdecl.
 
J

John Bode

(e-mail address removed) wrote:
You can simplify that to
void call_fpn( void ( * fp[ 3 ] )( void ) )

You seem to be quite good at this:

Consider that parameter type, call it T:

void (*fp[3])void

void (*fp[3])(void)
How could I modify T to end up with an array [N] of T?

Well, let's make sure we understand what T is. To parse a hairy
declaration, I start by finding the leftmost identifier, then work my
way out, remembering that [] and () bind before *:

fp -- fp
fp[3] -- is a 3-element array
*fp[3] -- of pointers
(*fp[3])(void) -- to functions
void (*fp[3])(void) -- returning void

So you want an N-element array of 3-element arrays of pointers to
functions returning void. So we build it up as follows:

fp -- fp
fp[N] -- is an N-element array
fp[N][3] -- of 3-element arrays
*fp[N][3] -- of pointers
(*fp[N][3])(void) -- to functions
void (*fp[N][3])(void) -- retuning void
How could I modify T to have a pointer to T?

fp -- fp
*fp -- is a pointer
(*fp)[3] -- to a 3-element array
*(*fp)[3] -- of pointers
(*(*fp)[3])(void) -- to functions
void (*(*fp)[3])(void) -- returning void
How could I modify T to have a function returning type T?

fp -- fp
fp() -- is a function
*fp() -- returning a pointer
(*fp())[3] -- to a 3-element array
*(*fp())[3] -- of pointers
(*(*fp())[3])(void) -- to functions
void (*(*fp())[3])(void) -- returning void

Please add any parentheses that might be needed.

(I need ask a similar question in a different guise recently. But no
replies, so it was either incredibly difficult, or so trivial that
nobody could understand why I was even asking. I contrived a solution
of sorts but it was unsatisfactory.)

-- Thanks,

Bartc

I'm not sure when I hit on this particular system for reading and
building hairy declarators, but I've had pretty good success with it.
You can also try to work your way from the outside in, using
substitution:

void F(void) -- F = (*P)
void (*P)(void) -- P = fp[3]
void (*fp[3])(void)

but I find the first method more straightforward, and more useful for
building complex declarations.
 
B

Ben Bacarisse

Functions, you need to add an extra asterisk (*), ie
int foo(int);
int (*)(int)

They are not the same type. The declaration with a name would be

int (*foo)(int);

and the "rule" correctly gives the cast operator: (int (*)(int)).
 

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

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top