By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,854 Members | 2,015 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,854 IT Pros & Developers. It's quick & easy.

Ah've got them Function Pointer blues

P: n/a
Folks,

I've been playing with C programs for 25 years (not professionally -
self-taught), and although I've used function pointers before, I've never
got my head around them enough to be able to think my way through what I
want to do now. I don't know why - I'm fine with most other aspects of the
language, but my brain goes numb when I'm reading about function pointers!

I would like to have an array of structures, something like

struct FS
{ <function pointer>;
<some other variables>;
};

My problem is that the <function pointeris of unknown type - in
function_structure[2] it may be

int func_1(int, int) {....}

in function_structure[5], it may be

void func_2(char **cpt) {....}

etc.

I would like to initialise the array directly, like
struct FS function_structure[] = {{ ....}, {....}, ...., {....}};

.... but I'm really shaky on what to put in those braces. I have been
playing with it, but so far unsuccessfully.

Is it possible? How do I declare the pointer in the structure, and how do I
assign a pointer value to it? And when I call it, how do I pass arguments
from the program? Could somebody give me a very simple example?

This isn't a homework thing, by the way - I write mostly little programs
that get used at work by colleagues. It improves my street-cred
(geek-cred? - well, no - I've just blown that notion!).

Incidentally, this may not be the best way to design the program, so I'd
like to ask about that too.
Can anybody suggest a newsgroup? (program architecture isn't really C)

Thanks,

MikeC
--
Mental decryption required to bamboozle spam robots:

mijewen$btconnect*com
$ = @
* = dot
Aug 20 '08 #1
Share this Question
Share on Google+
20 Replies


P: n/a
"MikeC" <Mi*******@btconnect.comwrites:

<snip>
I would like to have an array of structures, something like

struct FS
{ <function pointer>;
<some other variables>;
};

My problem is that the <function pointeris of unknown type - in
function_structure[2] it may be

int func_1(int, int) {....}

in function_structure[5], it may be

void func_2(char **cpt) {....}

etc.
That is not a problem since a function pointer of one type can be
converted to a function pointer of another type. The simplest is to
pick either a generic function pointer type and use that (the type
void (*)() is often used for this) or to pick the most common, thereby
cutting down the number of conversions needed.

Note that you need to convert the pointer to the right type at the
point of call.
I would like to initialise the array directly, like
struct FS function_structure[] = {{ ....}, {....}, ...., {....}};
Well, using the idea of a bland generic function pointer and using
typedefs to make the syntax simple:

typedef void function();

The struct will the look like this:

struct FS {
function *fp;
/* other data */
};

and you set up an array of them like this:

struct FS function_structure[] = {
{(function *)func_1, /* other data */},
{(function *)func_2, /* other data */}
};

The function call is horrible, though. function_structure[1].fp is of
type 'function *' and must be converted to 'void (*)(char **)' so you
need to write:

((void (*)(char **))function_structure[1].fp)(argv);
... but I'm really shaky on what to put in those braces. I have been
playing with it, but so far unsuccessfully.
You can simplify the casts with typedefs for you common pointer types
if you like.
Is it possible? How do I declare the pointer in the structure, and how do I
assign a pointer value to it? And when I call it, how do I pass arguments
from the program? Could somebody give me a very simple example?
--
Ben.
Aug 20 '08 #2

P: n/a
On 20 ago, 20:14, "MikeC" <Mike.B...@btconnect.comwrote:
Folks,

I've been playing with C programs for 25 years (not professionally -
self-taught), and although I've used function pointers before, I've never
got my head around them enough to be able to think my way through what I
want to do now. *I don't know why - I'm fine with most other aspects ofthe
language, but my brain goes numb when I'm reading about function pointers!

I would like to have an array of structures, something like

struct FS
{ <function pointer>;
* *<some other variables>;

};

My problem is that the <function pointeris of unknown type - in
function_structure[2] it may be

int func_1(int, int) {....}

in function_structure[5], it may be

void func_2(char **cpt) *{....}

etc.

I would like to initialise the array directly, like
*struct FS *function_structure[] = {{ ....}, {....}, ...., {....}};

... but I'm really shaky on what to put in those braces. *I have been
playing with it, but so far unsuccessfully.

Is it possible? *How do I declare the pointer in the structure, and howdo I
assign a pointer value to it? *And when I call it, how do I pass arguments
from the program? *Could somebody give me a very simple example?

This isn't a homework thing, by the way - I write mostly little programs
that get used at work by colleagues. *It improves my street-cred
(geek-cred? - well, no - I've just blown that notion!).

Incidentally, this may not be the best way to design the program, so I'd
like to ask about that too.
Can anybody suggest a newsgroup? (program architecture isn't really C)

Thanks,

MikeC

--
Mental decryption required to bamboozle spam robots:

mijewen$btconnect*com
$ = @
* = dot
as Ben Becarisse said, do make your code more readable use the
typedef,

/* funcPtr is a pointer function that has two int
as argument, and return int */
typedef int (*funcPtr)(int, int);

now in your structure

struct your_struct {
funcPtr func;
};

now to initialize your structure

struct your_function t[] = {
{&anyfunction /* with the same type of funcPtr */ },
{ /* here more declarations */ }
};

now to use

(t[0].func)(argument_1, argument_2);

a more complete example

------ start ------
#include <stdio.h>

typedef int (*funcPtr)(int, int);

struct test {
funcPtr func;
int a, b;
};

int print_sum(int a, int b)
{
printf("%d\n", a + b);
return a + b;
}

int main(void) {
struct test t[] = {
{&print_sum, 2, 2},
{&print_sum, 5, 5}
};

(*(t[0].func))(t[0].a, t[0].b);
(t[1].func)(t[1].a, t[1].b);
/* the two ways is valid, but the second is more preferred
and is supported since of c89 standard */
return 0;
}
------- end --------
Aug 21 '08 #3

P: n/a
voidpointer <di************@gmail.comwrites:
On 20 ago, 20:14, "MikeC" <Mike.B...@btconnect.comwrote:
>I would like to have an array of structures, something like

struct FS
{ <function pointer>;
* *<some other variables>;

};

My problem is that the <function pointeris of unknown type - in
function_structure[2] it may be

int func_1(int, int) {....}

in function_structure[5], it may be

void func_2(char **cpt) *{....}

etc.
<snip>
>MikeC

--
Mental decryption required to bamboozle spam robots:

mijewen$btconnect*com
$ = @
* = dot
Best not to quote sig block (unless you are commenting on them)
as Ben Becarisse said, do make your code more readable use the
typedef,

/* funcPtr is a pointer function that has two int
as argument, and return int */
typedef int (*funcPtr)(int, int);
I prefer to not hide the pointer in the typedef. I can see you agree
because you felt the need to reveal the pointerness in the name. "*" is
shorter that "Ptr" and...
now in your structure

struct your_struct {
funcPtr func;
function *func;

Is just as easy to read (for someone who has had to "get" pointers).

It is a small point (and by no means universally agreed upon) but it
seems worth noting. It has the huge benefit that you can avoid a lot
of the (*name)(...) syntax that seems to be the stumbling block for so
many people.
};

now to initialize your structure

struct your_function t[] = {
{&anyfunction /* with the same type of funcPtr */ },
{ /* here more declarations */ }
};

now to use

(t[0].func)(argument_1, argument_2);
The OP was interested in there being different function types. You
got to show the neat version!
a more complete example

------ start ------
#include <stdio.h>

typedef int (*funcPtr)(int, int);

struct test {
funcPtr func;
int a, b;
};

int print_sum(int a, int b)
{
printf("%d\n", a + b);
return a + b;
}

int main(void) {
struct test t[] = {
{&print_sum, 2, 2},
{&print_sum, 5, 5}
};

(*(t[0].func))(t[0].a, t[0].b);
(t[1].func)(t[1].a, t[1].b);
/* the two ways is valid, but the second is more preferred
and is supported since of c89 standard */
I prefer t[1].func(t[1].a, t[1].b); because I don't like extra
parentheses, but that is also debatable.
return 0;
}
------- end --------
--
Ben.
Aug 21 '08 #4

P: n/a
Gentlefolk,

You're good people. Your time and attention are very much appreciated.

Reading through it, it all makes sense - though I still have to work it into
operation.
I think the problem that I have (and maybe other people have) is that if you
have a pointer to a variable (of whatever type), and you execute

*foo = bar

you can easily see the mechanism of what happens. You'll laugh at the
analogy, but to me, it's like the postman handing the value to the variable
directly through the front door, but when it's a function pointer, the
postman comes to the door, gets on his mobile phone, and tells somebody else
to take the arguments around to the back door. They don't get to the
function by the same mechanism that gets a value to a dereferenced variable.

What I have learned, or at least had my eyes opened to from your
instructions, is that you can make a cast to a function pointer. I never
thought of that before, and I don't think I've read about it. Well, maybe I
did, but my brain was numb.

Thanks again for freely sharing your expertise.

MikeC

"Ben Bacarisse" <be********@bsb.me.ukwrote in message
news:87************@bsb.me.uk...
voidpointer <di************@gmail.comwrites:
>On 20 ago, 20:14, "MikeC" <Mike.B...@btconnect.comwrote:
>>I would like to have an array of structures, something like

struct FS
{ <function pointer>;
<some other variables>;

};

My problem is that the <function pointeris of unknown type - in
function_structure[2] it may be

int func_1(int, int) {....}

in function_structure[5], it may be

void func_2(char **cpt) {....}

etc.
<snip>
>>MikeC

--
Mental decryption required to bamboozle spam robots:

mijewen$btconnect*com
$ = @
* = dot

Best not to quote sig block (unless you are commenting on them)
>as Ben Becarisse said, do make your code more readable use the
typedef,

/* funcPtr is a pointer function that has two int
as argument, and return int */
typedef int (*funcPtr)(int, int);

I prefer to not hide the pointer in the typedef. I can see you agree
because you felt the need to reveal the pointerness in the name. "*" is
shorter that "Ptr" and...
>now in your structure

struct your_struct {
funcPtr func;

function *func;

Is just as easy to read (for someone who has had to "get" pointers).

It is a small point (and by no means universally agreed upon) but it
seems worth noting. It has the huge benefit that you can avoid a lot
of the (*name)(...) syntax that seems to be the stumbling block for so
many people.
>};

now to initialize your structure

struct your_function t[] = {
{&anyfunction /* with the same type of funcPtr */ },
{ /* here more declarations */ }
};

now to use

(t[0].func)(argument_1, argument_2);

The OP was interested in there being different function types. You
got to show the neat version!
>a more complete example

------ start ------
#include <stdio.h>

typedef int (*funcPtr)(int, int);

struct test {
funcPtr func;
int a, b;
};

int print_sum(int a, int b)
{
printf("%d\n", a + b);
return a + b;
}

int main(void) {
struct test t[] = {
{&print_sum, 2, 2},
{&print_sum, 5, 5}
};

(*(t[0].func))(t[0].a, t[0].b);
(t[1].func)(t[1].a, t[1].b);
/* the two ways is valid, but the second is more preferred
and is supported since of c89 standard */

I prefer t[1].func(t[1].a, t[1].b); because I don't like extra
parentheses, but that is also debatable.
>return 0;
}
------- end --------

--
Ben.

Aug 21 '08 #5

P: n/a
MikeC wrote:
[...]
I would like to have an array of structures, something like

struct FS
{ <function pointer>;
<some other variables>;
};

My problem is that the <function pointeris of unknown type - in
function_structure[2] it may be

int func_1(int, int) {....}

in function_structure[5], it may be

void func_2(char **cpt) {....}

etc.
How come the functions have different signature and what do you want to
achieve? Please, tell us a bit more about the underlying problem.
August
Aug 21 '08 #6

P: n/a

"August Karlstrom" <fu********@comhem.sewrote in message
news:g8**********@aioe.org...
MikeC wrote:
[...]
>I would like to have an array of structures, something like

struct FS
{ <function pointer>;
<some other variables>;
};

My problem is that the <function pointeris of unknown type - in
function_structure[2] it may be

int func_1(int, int) {....}

in function_structure[5], it may be

void func_2(char **cpt) {....}

etc.

How come the functions have different signature and what do you want to
achieve? Please, tell us a bit more about the underlying problem.
August
Well, I would have done that in the first place, but that's to do with
architecture, not with C, and this is a C group, and flames burn me. In my
original post, I asked:

"Incidentally, this may not be the best way to design the program, so I'd
like to ask about that too.
Can anybody suggest a newsgroup? (program architecture isn't really C)"

However, as you ask ...

I haven't finished specifying the program yet - I keep having bigger and
better ideas - but I want to write a text macro engine. It will interpret
commands from a (text) command file, executing them on an input (read only)
file, and producing an output file. The commands will be, for example

copy off // don't copy anythying from the input file to the output file
find_forward "a text string"
move_left 6 // characters
copy on // this causes any character scanned by the cursor to be copied to
the output file
loop 6 // times
{ <more commands>
}
etc....

.... you get the idea.
I wanted to run through the command (program) file and compile it into a
forth-like stack (yes, I'm a dinosaur), with each stack element being a
structure, which contains, among other things, a pointer to the function
that will execute the command. The commands do different things, so they
have different signatures, hence my question.

Among all the ways of solving this problem (the architecture problem), I'm
sure people who have spent a life in preofeesional programming will know of
much better methods, and probably be able to pull in other
packages/libraries that would do a lot of the work - but I don't know about
those. I usually write programs from scratch, and write everything.

Last night, I wrote char *stristr(char *str) because it isn't in the
library - though I'm sure it's somewhere (though I wouldn't know where to
look). I'm rather pleased with it! :-)

Regards,

MikeC

Aug 22 '08 #7

P: n/a
"MikeC" <Mi*******@btconnect.comwrites:
"August Karlstrom" <fu********@comhem.sewrote in message
<snip>
>How come the functions have different signature and what do you want to
achieve? Please, tell us a bit more about the underlying problem.
<snip>
However, as you ask ...

I haven't finished specifying the program yet - I keep having bigger and
better ideas - but I want to write a text macro engine. It will interpret
commands from a (text) command file, executing them on an input (read only)
file, and producing an output file. The commands will be, for example

copy off // don't copy anythying from the input file to the output file
find_forward "a text string"
move_left 6 // characters
copy on // this causes any character scanned by the cursor to be copied to
the output file
loop 6 // times
{ <more commands>
}
etc....

... you get the idea.
I wanted to run through the command (program) file and compile it into a
forth-like stack (yes, I'm a dinosaur), with each stack element being a
structure, which contains, among other things, a pointer to the function
that will execute the command. The commands do different things, so they
have different signatures, hence my question.
This does not follow automatically from what you have said. I have
done similar things and there is no reason why the functions /need/ to
have different types. One way to look at it is that the functions all
modify the state of a "text copying virtual machine". I.e. each one
takes a pointer to a structure that describes that program's state:
the file positions, variable bindings, stack and so on.

While there is a cost here (all the state get piled into one place)
the payoff is that you don't need a big switch effectively doing
run-time type checking. Remember I said that at the time of the call
the function pointer must be cast to the correct type? You end up
with a messy if-then-else chain (or a switch) resolving the correct
way to call each of the various kinds. It is well worth trying to get
them all to be the same.

--
Ben.
Aug 22 '08 #8

P: n/a

"Ben Bacarisse" <be********@bsb.me.ukwrote in message
news:87************@bsb.me.uk...
"MikeC" <Mi*******@btconnect.comwrites:
> The commands will be, for example

copy off // don't copy anythying from the input file to the output file
find_forward "a text string"
move_left 6 // characters
copy on // this causes any character scanned by the cursor to be copied
to
the output file
loop 6 // times
{ <more commands>
}
etc....

... you get the idea.
I wanted to run through the command (program) file and compile it into a
forth-like stack, with each stack element being a
structure, which contains, among other things, a pointer to the function
that will execute the command.

This does not follow automatically from what you have said. I have
done similar things and there is no reason why the functions /need/ to
have different types. One way to look at it is that the functions all
modify the state of a "text copying virtual machine". I.e. each one
takes a pointer to a structure that describes that program's state:
the file positions, variable bindings, stack and so on.

While there is a cost here (all the state get piled into one place)
the payoff is that you don't need a big switch effectively doing
run-time type checking. Remember I said that at the time of the call
the function pointer must be cast to the correct type? You end up
with a messy if-then-else chain (or a switch) resolving the correct
way to call each of the various kinds. It is well worth trying to get
them all to be the same.

--
Ben.
Thanks Ben, but I'm not sure I understand what you are thinking about.
The instructions above are a small sub-set of the instructions that will be
available.

find_forward "a text string" takes a string argument.
move_left 6 takes a decimal integer.
add var_2 14 takes a variable and a constant

I will have variables which I can add together, subtract, do simple
arithmetic, etc.

It seems to me all the functions are different. I can't envisage what you
have in mind - but then, you probably have a wealth of experince and
shoulder-rubbing with other programmers. I've been doing it for a long
time, but I have never known anybody else with an interest in it.

I can have a state machine to handle the text, yes, but it will have quite a
lot of buttons to push, and sometimes, two or three buttons in combination
to get it to the next state. Actually, the concept of a state machine had
not occurred to me. Thanks - I'll give that some thought.

What I have in mind would require a degree of pre-compilation, which would
require a switch, but I was planning to use the function pointers to replace
the switch as described in http://www.newty.de/fpt/intro.html. At run-time,
it would use the concepts of the Forth virtual machine, which is a simple,
reverse polish, stack-based machine. Very quick at run time for a
semi-interpreted language.

.... but we're getting quite off-topic. Is there an architecture group that
would be more appropriate?

Thanks,

MikeC
Aug 22 '08 #9

P: n/a
"MikeC" <Mi*******@btconnect.comwrites:
"Ben Bacarisse" <be********@bsb.me.ukwrote in message
news:87************@bsb.me.uk...
>"MikeC" <Mi*******@btconnect.comwrites:
>> The commands will be, for example

copy off // don't copy anythying from the input file to the output file
find_forward "a text string"
move_left 6 // characters
copy on // this causes any character scanned by the cursor to be copied
to
the output file
loop 6 // times
{ <more commands>
}
etc....

... you get the idea.
I wanted to run through the command (program) file and compile it into a
forth-like stack, with each stack element being a
structure, which contains, among other things, a pointer to the function
that will execute the command.

This does not follow automatically from what you have said. I have
done similar things and there is no reason why the functions /need/ to
have different types. One way to look at it is that the functions all
modify the state of a "text copying virtual machine". I.e. each one
takes a pointer to a structure that describes that program's state:
the file positions, variable bindings, stack and so on.

While there is a cost here (all the state get piled into one place)
the payoff is that you don't need a big switch effectively doing
run-time type checking. Remember I said that at the time of the call
the function pointer must be cast to the correct type? You end up
with a messy if-then-else chain (or a switch) resolving the correct
way to call each of the various kinds. It is well worth trying to get
them all to be the same.

--
Ben.
Best not to quote sig blocks.
Thanks Ben, but I'm not sure I understand what you are thinking about.
The instructions above are a small sub-set of the instructions that will be
available.

find_forward "a text string" takes a string argument.
move_left 6 takes a decimal integer.
add var_2 14 takes a variable and a constant

I will have variables which I can add together, subtract, do simple
arithmetic, etc.

It seems to me all the functions are different.
If you start to generalise, I'd bet they merge into a common type.
For example, why have only string literals? If you can:

set myvar next(3)
find_forward myvar

To pick put "abc" and skip to the next "abc". Or

set myvar next(3)
find_forward myvar+myvar

to skip to "abcabc" then suddenly find_forward needs an "expression"
type object just like everything else. And if some operation needs
more than one piece of data, it can be solved by have a way to
represent "tuples" like (42, "a string") as a single value.

Now, you may has a design the does not this generality, so by all
means use separate types, but as you extend the functions of your
program, I bet you will find the types start to come together. This
is a case where generalising early, can help.

I have just finished the message I noted that you are planning on
something like Forth. That makes my plan all the better, but I will
leave this general idea here anyway.
I can't envisage what you
have in mind - but then, you probably have a wealth of experince and
shoulder-rubbing with other programmers. I've been doing it for a long
time, but I have never known anybody else with an interest in it.
That is a shame. It really helps to talk over designs.
comp.programming is good place for general discussions.
I can have a state machine to handle the text, yes, but it will have quite a
lot of buttons to push, and sometimes, two or three buttons in combination
to get it to the next state. Actually, the concept of a state machine had
not occurred to me. Thanks - I'll give that some thought.

What I have in mind would require a degree of pre-compilation, which would
require a switch, but I was planning to use the function pointers to replace
the switch as described in http://www.newty.de/fpt/intro.html. At run-time,
it would use the concepts of the Forth virtual machine, which is a simple,
reverse polish, stack-based machine. Very quick at run time for a
semi-interpreted language.
If you are going forth-ish then I think you won't need separate types
at all. All forth opcodes act on "the stack" -- they all have the
same type:

find_forward: pop "thing" from stack, scan for it.
move_left: pop "thing" from stack and treat it as a number f
places to move
add: pop two things. One is treated as a variable name (or
reference) the second is a value.

You will need a way to represent stack values, but all operations just
need the internal scanning state and the stack to do their work.
... but we're getting quite off-topic. Is there an architecture group that
would be more appropriate?
comp.programming is the best I can think of.

--
Ben.
Aug 22 '08 #10

P: n/a
"MikeC" <Mi*******@btconnect.comwrote in message
news:jc******************************@bt.com...
Folks,
Well, Folks,

Following advice/inspiration given in this thread, I have spent some time
playing with function pointers, but I still haven't been able to make them
work the way I want them to.
Please see my comments in the last few lines of main().

void func_a(char *str)
// stupid function - increments each character in the string
{ char *pt = str;
while(*pt != '\0')
{ *pt = (*pt)++ & 0xff;
pt++;
}
}

int func_b(void)
// returns number of ticks since midnight
{ return rawclock();
}

char *func_c(char *str)
// returns a pointer to the mid-point of the string
{ char *pt = str;
while(*pt) pt++;
return str + (pt - str)/2;
}

int mult_ab(int a, int b)
// returns the product of two numbers
{ return (a * b);
}

main(int argc, char *argv[])
{ int i1, i2;
char str[] = "1234567890abcdefgh";
char *pt;
void (*fpv)();
int (*fpi)();
char *(*fpc)();

// the following work fine
fpv = func_a;
fpv(str); // this modifies the string as expected

fpi = (void*)func_a;
fpi(str); // this also compiles and works.

fpi = func_b; // this works too, but func_b expects to return an int,
i1 = fpi(); // and fpi is an int pointer, so I would /expect/ it to work

fpi = mult_ab; // this also works - also expected, as fpi returns an int
i2 = fpi(3, 5);

fpc = func_c; // this assignment compiles
fpi = fpc; // this one gives a compile warning. No luck in casting it.
pt = (char *)fpi(str); // but this line shows that it worked.
//fpi = ((int*)())fpc; // this cast fails compilation
//fpi = (int)(*)())fpc; // ... as does this one. Tried various fanciful
// and desperate things without success
// I have also been unable to cast the void function pointer, fpv, to
point func_b or func_c,
// and to return an int or an char*
}

I'm sinking!
(Don't ask what I'm sinking about - I've heard that one!)

MikeC.
mijewen$btconnect*com
$ = @
* = dot There are 10 kinds of people in the world - those who understand
binary, and those who don't.


Aug 28 '08 #11

P: n/a
Just as an introduction to this article, my implementation's diagnostics
for posted code (after C99 comments removed):

foo.c:2: warning: no previous prototype for `func_a'
foo.c:10: warning: no previous prototype for `func_b'
foo.c: In function `func_b':
foo.c:10: warning: implicit declaration of function `rawclock'
foo.c: At top level:
foo.c:14: warning: no previous prototype for `func_c'
foo.c:20: warning: no previous prototype for `mult_ab'
foo.c:24: warning: return-type defaults to `int'
foo.c: In function `main':
foo.c:27: warning: function declaration isn't a prototype
foo.c:28: warning: function declaration isn't a prototype
foo.c:29: warning: function declaration isn't a prototype
foo.c:34: warning: ANSI forbids assignment between function pointer and
`void *'
foo.c:44: warning: assignment from incompatible pointer type
foo.c:45: warning: cast does not match function type
foo.c:46: parse error before `)'
foo.c:47: parse error before `)'
foo.c:47: parse error before `)'
foo.c:23: warning: unused parameter `argc'
foo.c:23: warning: unused parameter `argv'
foo.c:48: warning: control reaches end of non-void function
make: *** [foo.o] Error 1

Comments on code follow:

MikeC said:

<snip>
void func_a(char *str)
// stupid function - increments each character in the string
{ char *pt = str;
while(*pt != '\0')
{ *pt = (*pt)++ & 0xff;
The behaviour of the code is undefined from this point. The problem is that
you are modifying *pt twice between consecutive sequence points.

<snip>
// the following work fine
fpv = func_a;
fpv(str); // this modifies the string as expected
Unlucky. If it had not done so (and there's no reason why it should and no
reason why it shouldn't), you might have been motivated to investigate.
fpi = (void*)func_a;
The cast is unwise, since C doesn't provide any guaranteed conversion
between function pointers and void *. You could, however, have used a cast
to (int(*)()) - although I can't help wondering why you would want to -
why not just use a function pointer of the proper type in the first place?
fpi(str); // this also compiles and works.

fpi = func_b; // this works too, but func_b expects to return an int,
i1 = fpi(); // and fpi is an int pointer, so I would /expect/ it to
work
No, fpi is not an int pointer. fpi is a pointer to a function that returns
int.
fpi = mult_ab; // this also works - also expected, as fpi returns an
int i2 = fpi(3, 5);
My newsreader has, in this reply, wrapped the word 'int' to the start of
the next line. If you'd used /* comments */ that wouldn't have mattered.
Well, it doesn't really matter now either, since we both know what you
mean - but bear in mind that // comments are susceptible to being broken
by tools that format text as part of their job.

Back to C: fpi doesn't return anything, actually. It's a pointer, not a
function. It might /point/ to a function, but it is not itself a function.
fpc = func_c; // this assignment compiles
As one would expect.
fpi = fpc; // this one gives a compile warning. No luck in casting
it.
Why would you want to do that assignment in the first place? But if you
must cast (and casts help broken programs in much the same way that they
help broken legs - unfortunately, programs won't heal themselves like legs
do), do it like this: fpi = (int (*)())fpc;
pt = (char *)fpi(str); // but this line shows that it worked.
Oh dear. Yes, sometimes if you hit a square peg hard enough, it *will* fit
in the round hole.
//fpi = ((int*)())fpc; // this cast fails compilation
Yes, I'm not surprised. You're casting to a function type, not a function
pointer type, and that isn't ever going to work.
//fpi = (int)(*)())fpc; // ... as does this one. Tried various fanciful
// and desperate things without success
Count the ( parentheses in that line. Now count the ) parentheses.
// I have also been unable to cast the void function pointer, fpv, to
point func_b or func_c,
// and to return an int or an char*
I am at a loss to understand why you would want to.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Aug 29 '08 #12

P: n/a

"Richard Heathfield" <rj*@see.sig.invalidwrote in message
news:hs*********************@bt.com...
Just as an introduction to this article, my implementation's diagnostics
<snip>
Thanks for your help, Richard. I was rather hoping for help from Ben
Bacarisse, as he had answered several of the preceeding points, and knew the
history and thread of this question. Even without reading through the
preamble of questions, however, some of the things you said are very
helpful.
>
>void func_a(char *str)
// stupid function - increments each character in the string
{ char *pt = str;
while(*pt != '\0')
{ *pt = (*pt)++ & 0xff;

The behaviour of the code is undefined from this point. The problem is
that
you are modifying *pt twice between consecutive sequence points.
Yes, it could well be that it's untidy C, but it was just a quick lashup of
a function that took an argument, and returned none.
It wasn't to use in anything more than this example. It's possible it would
have not had the desired outcome under a different compiler, but it worked
on mine. The question I was asking was, in any case, not to do with making
my program work, but with understanding how to use function pointers. My
compiler is not on the machine I'm using at the moment, so stuff like
mis-matching parentheses is just due to a typo in transferring the info.
<snip>
>// the following work fine
fpv = func_a;
fpv(str); // this modifies the string as expected

Unlucky. If it had not done so (and there's no reason why it should and no
reason why it shouldn't), you might have been motivated to investigate.
Because there was no cast? Should I have used
fpv = (void(*)())func_a; //?
> fpi = (void*)func_a;

The cast is unwise, since C doesn't provide any guaranteed conversion
between function pointers and void *. You could, however, have used a cast
to (int(*)()) - although I can't help wondering why you would want to -
why not just use a function pointer of the proper type in the first place?
Ah, well that was my original question. I want to have an array of function
pointers, then
have them point to functions of different types, so
func[0] points to int aaa(int, char*)
func[1] points to void bbb(char *)
func[2] points to char *ccc(char *, struct KKK *kkk)
etc.

In reality, this will not be an array of pointers, but an array of
structures, in which each structure will contain a function pointer and
other variables.
It's explained in the previous parts of this thread.
My problem is that I'm (clearly!) struggling to understand function
pointers.

To bring my question down to the simplest form, if I have a function

int return_42(void)
{ return 42;
}

then I declare a function pointer...

int main()
{ void (*fpv)();
int i;

fpv = ????
i = <cast>fpv;
}

My question is this - how do I make fpv point to the function return_42, and
how do I induce it to assign the return value to i?

If I can understand that, I'm sure I can resolve the rest of my problem.

Many thanks,
MikeC
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999

Aug 29 '08 #13

P: n/a
MikeC wrote:
Folks,

I've been playing with C programs for 25 years (not professionally -
self-taught), and although I've used function pointers before, I've never
got my head around them enough to be able to think my way through what I
want to do now.
I've seen arrays of function pointers
to the same type of functions used,
when one of a bunch of functions is selected according
to which interrupt just occured.

When I compare sorting functions,
I use an array of structures containing
function pointers to same type of sorting functions,
to test them sequentially in a loop.

http://www.mindspring.com/~pfilandr/C/q_sort/q_sort.c
http://www.mindspring.com/~pfilandr/...ver/e_driver.c

But I'm unfamiliar with the use of
various types of function pointers
in the same part of a program.

--
pete
Aug 29 '08 #14

P: n/a
"MikeC" <Mi*******@btconnect.comwrites:
[...]
To bring my question down to the simplest form, if I have a function

int return_42(void)
{ return 42;
}

then I declare a function pointer...

int main()
{ void (*fpv)();
int i;

fpv = ????
i = <cast>fpv;
}

My question is this - how do I make fpv point to the function return_42, and
how do I induce it to assign the return value to i?
Use prototypes consistently. Empty parentheses in a function
declaration mean that the function has an unspecified number and
type(s) of parameters. <OT>It's different in C++.</OT To declare
that a function has no parameters, use "(void)".

You can make fpv (a pointer to function returning void) point to
return_42 (a function returning int), but you cannot make an indirect
call using the value of fpv, because the types don't match. The
behavior of such a call is undefined.

Things to remember:

You can convert between any pointer-to-function type and any other
pointer-to-function type. Such conversions always require a cast;
they're never done implicitly.

For object pointers, void* is a generic pointer type. For function
pointers, since they're *all* freely convertible, you can use any
function pointer type you like as a generic type. It's probably best
to use the simplest such type, ``void (*)(void)''.

When you call a function via a pointer-to-function, you must use a
pointer-to-function whose target type matches the type of the actual
function you're calling. The compiler won't check this for you, so
it's easy to get this wrong and invoke undefined behavior. For
example, if you call a function that returns an int via a pointer to a
function returning void, the code for the call will assume that the
function returns no value. Arbitrarily bad things can happen. If
you're particularly unlucky, it will appear to work, making it harder
to detect the bug.

Here's an example of the right way to do it. I use typedefs to make
the code easier.

#include <stdio.h>

/*
* Note that we can't use these typedefs directly; you
* can't declare a function object. But we can declare
* objects that are pointers to functions. I could
* reasonably have declared typedefs for the pointer types,
* but I dislike hiding pointers behind typedefs.
*
* "function_returning_void" might better have been called
* "generic_function".
*/
typedef int (function_returning_int) (void);
typedef void(function_returning_void)(void);

int return_42(void)
{
return 42;
}

int main(void)
{
/*
* Declare fpv as a pointer to a function_returning_void.
*/
function_returning_void *fpv;

int i;

/*
* return_42, as an expression, is a pointer to a
* function_returning_int. fpv is of type pointer to
* function_returning_void. Since there's no implicit
* conversion, we need to use a cast.
*/
fpv = (function_returning_void *)return_42;

/*
* Now we can't make a function call using the value
* of fpv directly, because the types don't match.
* The behavior of such a call would be undefined.
* So we take the value of fpv, which is a pointer to
* function_returning_void, and convert it *back* to a
* pointer to function_returning_int. We can now call
* return_42() indirectly through this pointer value,
* which is now of the correct type.
*/
i = ((function_returning_int *)fpv)();

/*
* Output: "i = 42"
*/
printf("i = %d\n", i);

return 0;
}

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Aug 29 '08 #15

P: n/a
MikeC wrote:
"Richard Heathfield" <rj*@see.sig.invalidwrote in message
news:hs*********************@bt.com...
....
void func_a(char *str)
// stupid function - increments each character in the string
{ char *pt = str;
while(*pt != '\0')
{ *pt = (*pt)++ & 0xff;
The behaviour of the code is undefined from this point. The problem is
that
you are modifying *pt twice between consecutive sequence points.

Yes, it could well be that it's untidy C,
It's not untidy - it's got undefined behavior. That's pretty much the
nastiest thing the C standard can say about any piece of code. This
means that whether or not it does anything remotely resembling what
you want it to do is entirely a matter of luck. It is also,
incidentally, far from clear what you wanted the code to do. Does the
following rewrite match your intent?:

*pt = (1+*pt) & 0xFF;

There's a disease that afflicts many C newbies: they so fascinated by +
+ that they use even in it contexts where +1 is required. This is one
of those contexts.
// the following work fine
fpv = func_a;
fpv(str); // this modifies the string as expected
Unlucky. If it had not done so (and there's no reason why it should and no
reason why it shouldn't), you might have been motivated to investigate.
Because there was no cast?
A cast is not needed here, because fpv has the type (void(*)()). The
"()" indicates that it takes an unknown number of arguments of
unspecified types. As long at the promoted types of the arguments in
the function call match the actual type of the parameters of the
function definition, that is not a problem.

The problem is because func_a() has undefined behavior.
fpi = (void*)func_a;
The cast is unwise, since C doesn't provide any guaranteed conversion
between function pointers and void *. You could, however, have used a cast
to (int(*)()) - although I can't help wondering why you would want to -
why not just use a function pointer of the proper type in the first place?

Ah, well that was my original question. I want to have an array of function
pointers, then
have them point to functions of different types, so
func[0] points to int aaa(int, char*)
func[1] points to void bbb(char *)
func[2] points to char *ccc(char *, struct KKK *kkk)
If you're using a pointer to one function type, to store pointers to
functions with many different types, it will be absolutely essential
for you to keep track, in some fashion, of what the actual function
type is for each pointer is. You need to convert the function pointer
back to that type before you can actually use it.

....
To bring my question down to the simplest form, if I have a function

int return_42(void)
{ return 42;
}

then I declare a function pointer...

int main()
{ void (*fpv)();
int i;

fpv = ????
fvp = (void(*)()) return_42;
i = <cast>fpv;
i = ((int(*)(void))fpv)();
}
Aug 29 '08 #16

P: n/a
James, Many thanks for your comments. The best way to understand any
problem is to get various different views on the subject, so every little
helps - even being torn to shreds! :-)

MikeC

<ja*********@verizon.netwrote in message
news:24**********************************@d77g2000 hsb.googlegroups.com...
MikeC wrote:
>"Richard Heathfield" <rj*@see.sig.invalidwrote in message
news:hs*********************@bt.com...
...
>void func_a(char *str)
// stupid function - increments each character in the string
{ char *pt = str;
while(*pt != '\0')
{ *pt = (*pt)++ & 0xff;

The behaviour of the code is undefined from this point. The problem is
that
you are modifying *pt twice between consecutive sequence points.

Yes, it could well be that it's untidy C,

It's not untidy - it's got undefined behavior. That's pretty much the
nastiest thing the C standard can say about any piece of code. This
means that whether or not it does anything remotely resembling what
you want it to do is entirely a matter of luck. It is also,
incidentally, far from clear what you wanted the code to do. Does the
following rewrite match your intent?:

*pt = (1+*pt) & 0xFF;

There's a disease that afflicts many C newbies: they so fascinated by +
+ that they use even in it contexts where +1 is required. This is one
of those contexts.
>// the following work fine
fpv = func_a;
fpv(str); // this modifies the string as expected

Unlucky. If it had not done so (and there's no reason why it should and
no
reason why it shouldn't), you might have been motivated to investigate.
Because there was no cast?

A cast is not needed here, because fpv has the type (void(*)()). The
"()" indicates that it takes an unknown number of arguments of
unspecified types. As long at the promoted types of the arguments in
the function call match the actual type of the parameters of the
function definition, that is not a problem.

The problem is because func_a() has undefined behavior.
> fpi = (void*)func_a;

The cast is unwise, since C doesn't provide any guaranteed conversion
between function pointers and void *. You could, however, have used a
cast
to (int(*)()) - although I can't help wondering why you would want to -
why not just use a function pointer of the proper type in the first
place?

Ah, well that was my original question. I want to have an array of
function
pointers, then
have them point to functions of different types, so
func[0] points to int aaa(int, char*)
func[1] points to void bbb(char *)
func[2] points to char *ccc(char *, struct KKK *kkk)

If you're using a pointer to one function type, to store pointers to
functions with many different types, it will be absolutely essential
for you to keep track, in some fashion, of what the actual function
type is for each pointer is. You need to convert the function pointer
back to that type before you can actually use it.

...
>To bring my question down to the simplest form, if I have a function

int return_42(void)
{ return 42;
}

then I declare a function pointer...

int main()
{ void (*fpv)();
int i;

fpv = ????

fvp = (void(*)()) return_42;
> i = <cast>fpv;

i = ((int(*)(void))fpv)();
>}

Aug 29 '08 #17

P: n/a
Keith,

That's exactly what I wanted - a proper explanation, illustrated with
demonstrative examples.
Thank you so much. I'll go play with it (again!), and I'm sure it will set
me on the road to success.
It gives me a much better understanding of what function pointers are about,
and how to handle them.

BTW, I thought I had already sent this message, but as I don't see it there,
I guess I must have pressed the Kill button instead of the Send button (not
for the first time!), so my apologies if you get it twice.

Mike Collins.
"Keith Thompson" <ks***@mib.orgwrote in message
news:ln************@nuthaus.mib.org...
"MikeC" <Mi*******@btconnect.comwrites:
[...]
>To bring my question down to the simplest form, if I have a function

int return_42(void)
{ return 42;
}

then I declare a function pointer...

int main()
{ void (*fpv)();
int i;

fpv = ????
i = <cast>fpv;
}

My question is this - how do I make fpv point to the function return_42,
and
how do I induce it to assign the return value to i?

Use prototypes consistently. Empty parentheses in a function
declaration mean that the function has an unspecified number and
type(s) of parameters. <OT>It's different in C++.</OT To declare
that a function has no parameters, use "(void)".

You can make fpv (a pointer to function returning void) point to
return_42 (a function returning int), but you cannot make an indirect
call using the value of fpv, because the types don't match. The
behavior of such a call is undefined.

Things to remember:

You can convert between any pointer-to-function type and any other
pointer-to-function type. Such conversions always require a cast;
they're never done implicitly.

For object pointers, void* is a generic pointer type. For function
pointers, since they're *all* freely convertible, you can use any
function pointer type you like as a generic type. It's probably best
to use the simplest such type, ``void (*)(void)''.

When you call a function via a pointer-to-function, you must use a
pointer-to-function whose target type matches the type of the actual
function you're calling. The compiler won't check this for you, so
it's easy to get this wrong and invoke undefined behavior. For
example, if you call a function that returns an int via a pointer to a
function returning void, the code for the call will assume that the
function returns no value. Arbitrarily bad things can happen. If
you're particularly unlucky, it will appear to work, making it harder
to detect the bug.

Here's an example of the right way to do it. I use typedefs to make
the code easier.

#include <stdio.h>

/*
* Note that we can't use these typedefs directly; you
* can't declare a function object. But we can declare
* objects that are pointers to functions. I could
* reasonably have declared typedefs for the pointer types,
* but I dislike hiding pointers behind typedefs.
*
* "function_returning_void" might better have been called
* "generic_function".
*/
typedef int (function_returning_int) (void);
typedef void(function_returning_void)(void);

int return_42(void)
{
return 42;
}

int main(void)
{
/*
* Declare fpv as a pointer to a function_returning_void.
*/
function_returning_void *fpv;

int i;

/*
* return_42, as an expression, is a pointer to a
* function_returning_int. fpv is of type pointer to
* function_returning_void. Since there's no implicit
* conversion, we need to use a cast.
*/
fpv = (function_returning_void *)return_42;

/*
* Now we can't make a function call using the value
* of fpv directly, because the types don't match.
* The behavior of such a call would be undefined.
* So we take the value of fpv, which is a pointer to
* function_returning_void, and convert it *back* to a
* pointer to function_returning_int. We can now call
* return_42() indirectly through this pointer value,
* which is now of the correct type.
*/
i = ((function_returning_int *)fpv)();

/*
* Output: "i = 42"
*/
printf("i = %d\n", i);

return 0;
}

--
Keith Thompson (The_Other_Keith) ks***@mib.org
<http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Aug 29 '08 #18

P: n/a
MikeC wrote:
Keith,

Please don't top-post. Your replies belong following or interspersed
with properly trimmed quotes. See the majority of other posts in the
newsgroup, or:
<http://www.caliburn.nl/topposting.html>
Aug 29 '08 #19

P: n/a
On Aug 29, 10:27*am, "MikeC" <Mike.B...@btconnect.comwrote:
"Richard Heathfield" <r...@see.sig.invalidwrote in message
snip
void func_a(char *str)
// stupid function - increments each character in the string
{ char *pt = str;
* while(*pt != '\0')
* { *pt = (*pt)++ & 0xff;
The behaviour of the code is undefined from this point. The problem is
that
you are modifying *pt twice between consecutive sequence points.

Yes, it could well be that it's untidy C, but it was just a quick lashup of
a function that took an argument, and returned none.
It wasn't to use in anything more than this example. *It's possible it would
have not had the desired outcome under a different compiler, but it worked
on mine. *The question I was asking was, in any case, not to do with making
my program work, but with understanding how to use function pointers. *My
compiler is not on the machine I'm using at the moment, so stuff like
mis-matching parentheses is just due to a typo in transferring the info.
You are asking for help on a public forum. There are many here who
try to do just that. One technique for doing so is to compile and
execute the code to eliminate syntax issues and get a feel for what
works and what doesn't (possibly using a debugger). Once your "quick
lashup" function (that is supposedly unrelated to your question)
doesn't do what it claims (as you admit it may not on their system),
they have to wonder whether this is even the code your using.
Furthermore, undefined behavior can have delayed impacts that appear
to be caused by other issues.

While admittedly unlikely in this case, this undefined behavior could
have caused the problems you observed even if the rest of your code
had been perfect.
Aug 29 '08 #20

P: n/a
On Fri, 29 Aug 2008 11:00:41 -0700, Keith Thompson <ks***@mib.org>
wrote:
"MikeC" <Mi*******@btconnect.comwrites:
<snipped>
Use prototypes consistently. Empty parentheses in a function
declaration mean that the function has an unspecified number and
type(s) of parameters. <OT>It's different in C++.</OT To declare
that a function has no parameters, use "(void)".
Yes.
You can make fpv (a pointer to function returning void) point to
return_42 (a function returning int), but you cannot make an indirect
call using the value of fpv, because the types don't match. The
behavior of such a call is undefined.
Yes.
Things to remember:

You can convert between any pointer-to-function type and any other
pointer-to-function type. Such conversions always require a cast;
they're never done implicitly.
One exception: if you use pointer to unprototyped (unspecified but
K&R1 compatible args) function type, you can convert implicitly as
long as (just) the return type matches. But you can't necessarily use
the result to call, as noted above and detailed below.
For object pointers, void* is a generic pointer type. For function
pointers, since they're *all* freely convertible, you can use any
function pointer type you like as a generic type. It's probably best
to use the simplest such type, ``void (*)(void)''.

When you call a function via a pointer-to-function, you must use a
pointer-to-function whose target type matches the type of the actual
function you're calling. The compiler won't check this for you, so
it's easy to get this wrong and invoke undefined behavior. For
example, if you call a function that returns an int via a pointer to a
function returning void, the code for the call will assume that the
function returns no value. Arbitrarily bad things can happen. If
you're particularly unlucky, it will appear to work, making it harder
to detect the bug.
Emphatically yes, with again one exception: you must either
- call through a pointer to prototype that matches the actual routine;
- OR through a pointer to unprototyped AND the actual arguments, after
the default promotions (only), match the actual routine

The compiler can't check either of these for you, but the former is
(IMO) easier to reliably check manually thus preferable.
Here's an example of the right way to do it. I use typedefs to make
the code easier.

#include <stdio.h>

/*
* Note that we can't use these typedefs directly; you
* can't declare a function object. But we can declare
* objects that are pointers to functions. I could
* reasonably have declared typedefs for the pointer types,
* but I dislike hiding pointers behind typedefs.
*
You can _declare_ a function using a typedef, but you can't _define_
(aka implement) it. Since many people, including me, like to have
the/any declaration(s) and definition visually the same, this
discourages using such a typedef.
* "function_returning_void" might better have been called
* "generic_function".
*/
typedef int (function_returning_int) (void);
typedef void(function_returning_void)(void);
<snip rest>
- formerly david.thompson1 || achar(64) || worldnet.att.net
Sep 7 '08 #21

This discussion thread is closed

Replies have been disabled for this discussion.