Function pointer tables

B

Bartc

I'm having problems with the following code.

I have a table of function pointers, and a function pointer variable p which
steps through the functions.

But I'm not allowed to increment the variable using ++p.

What's the problem here?

Also, I may not be interested in returning from any of these functions (each
will call the next according to some global variable). Any recommended way
of doing this (throwing away return address) other than a crude asm("pop
R")?

Thanks,

Bart.


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

void f1(void);
void f2(void);
void f3(void);
void f4(void);

int main(void)
{
void (*table[])(void)={&f1,&f2,&f3,&f4}; /* table of function pointers */
void (*p)(void); /* pointer to one of the functions (I hope) */

p=table[0];

while(1)
{ (*p)(); /* Call function @p */
++p; /* COMPILE ERROR HERE */
};

}

void f1(void){puts("F1 CALLED");return;};
void f2(void){puts("F2 CALLED");return;};
void f3(void){puts("F3 CALLED");return;};
void f4(void){puts("F4 CALLED"); exit(0);};
 
M

myheartinamerica

/* Also, p needs to be a pointer to a function pointer. */

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

void f1(void);
void f2(void);
void f3(void);
void f4(void);

int main(void)
{
void (*table[])(void)={&f1,&f2,&f3,&f4}; /* table of function
pointers */
void (**p)(void); /* pointer to a function pointer */

p=table;

while(1)
{
(*(*p))(); /* Call function @p */
++p;

};
}

void f1(void){puts("F1 CALLED");return;};
void f2(void){puts("F2 CALLED");return;};
void f3(void){puts("F3 CALLED");return;};
void f4(void){puts("F4 CALLED"); exit(0);};
 
P

Peter Nilsson

I'm having problems with the following code.

I have a table of function pointers, and a function
pointer variable p which steps through the functions.

Think more basically of p as a pointer to an array
element.
But I'm not allowed to increment the variable using
++p.

What's the problem here?

Also, I may not be interested in returning from any of
these functions (each will call the next according to
some global variable). Any recommended way of doing
this (throwing away return address) other than a crude
asm("pop R")?

Thanks,

Bart.

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

void f1(void);
void f2(void);
void f3(void);
void f4(void);

int main(void)
{
void (*table[])(void)={&f1,&f2,&f3,&f4};
   /* table of function pointers */

This is an array of function pointers.
void (*p)(void);
   /* pointer to one of the functions (I hope) */

This is a function pointer, not a pointer to a
function pointer.
p=table[0];

while(1)
{ (*p)();    /* Call function @p */
  ++p;    /* COMPILE ERROR HERE */

};
}

void f1(void){puts("F1 CALLED");return;};
void f2(void){puts("F2 CALLED");return;};
void f3(void){puts("F3 CALLED");return;};
void f4(void){puts("F4 CALLED"); exit(0);};

The extra semi-colons are a syntax error too.
Simple typedefs will make this simpler.

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

void f1(void) { puts("F1 CALLED"); return; }
void f2(void) { puts("F2 CALLED"); return; }
void f3(void) { puts("F3 CALLED"); return; }
void f4(void) { puts("F4 CALLED"); exit(0); }

typedef void (*func_ptr)(void);

int main(void)
{
func_ptr table[] = { f1, f2, f3, f4 };
func_ptr *p;

for (p = table; p < table + 4; p++)
(*p)();

return 0;
}
 
V

vippstar

I'm having problems with the following code.

I have a table of function pointers, and a function pointer variable p which
steps through the functions.

But I'm not allowed to increment the variable using ++p.

What's the problem here?

Also, I may not be interested in returning from any of these functions (each
will call the next according to some global variable). Any recommended way
of doing this (throwing away return address) other than a crude asm("pop
R")?

Thanks,

Bart.

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

void f1(void);
void f2(void);
void f3(void);
void f4(void);

int main(void)
{
void (*table[])(void)={&f1,&f2,&f3,&f4}; /* table of function pointers */
void (*p)(void); /* pointer to one of the functions (I hope) */
You need void (**p)(void)
p=table[0];
and here, p = table;

The reason for this is simple:

table[0] is a void (*)(void), so p must be void (**)(void)
(like string[0] is char and p must be char *)

<snip>
 
B

Bartc

I'm having problems with the following code.

I have a table of function pointers, and a function pointer variable p
which
steps through the functions.
void (*table[])(void)={&f1,&f2,&f3,&f4}; /* table of function pointers
*/
void (*p)(void); /* pointer to one of the functions (I hope) */
You need void (**p)(void)
p=table[0];
and here, p = table;

The reason for this is simple:

table[0] is a void (*)(void), so p must be void (**)(void)
(like string[0] is char and p must be char *)

Ok, thanks for the replies.

So with ++p I was attempting to step to the next (actual) function, not the
next table entry. I understand now. C's declaration syntax isn't any clearer
though!
 
J

João Jerónimo

Bartc said:
Ok, thanks for the replies.

So with ++p I was attempting to step to the next (actual) function, not the
next table entry. I understand now.

Incrementing a pointer is syntactically correct. However, incrementing a
function pointer is not semantically possible.

That's more or less the case of arrays of functions. Theoretically, you
could do:
int func_array[6](int argument);
Meaning "func_array is an array of 6 functions, each taking one int and
returning int". This has no meaning in C semantics, however, because there
aren't objects of the type "array of functions".
C's declaration syntax isn't any clearer though!

C syntax is clear. It's not, however, the most intuitive!

The ideia is simple. You have an "array of foo" (where foo is a type). It's
(array's) symbol behaves arithmetically as a "pointer to foo". This means that:
- The operator [], that apparently is an indexing operator, actually acts
on pointers (and objects that arithmetically behave like pointers), by
summing it with the "index" and derreferencing it (that said, thing is
synctatic sugar for *(thing+i) )
- If you need to point to an array, you really want a pointer to the first
element of that array. For example, if you have an object of type "array of
chars" and you need to point to it, you'll need a "pointer to char".
Similary, if you have an object of type "array of pointers to functions",
and you need to point to it, you will need a "pointer to pointer to function".

Rather simple, but still has to be explained!

JJ
 
P

pete

Bartc said:
I'm having problems with the following code.

I have a table of function pointers, and a function pointer variable p which
steps through the functions.

But I'm not allowed to increment the variable using ++p.

What's the problem here?

Also, I may not be interested in returning from any of these functions (each
will call the next according to some global variable). Any recommended way
of doing this (throwing away return address) other than a crude asm("pop
R")?

Thanks,

Bart.

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

void f1(void);
void f2(void);
void f3(void);
void f4(void);

int main(void)
{
void (*table[])(void)={&f1,&f2,&f3,&f4}; /* table of function pointers */
void (*p)(void); /* pointer to one of the functions (I hope) */

p=table[0];

while(1)
{ (*p)(); /* Call function @p */
++p; /* COMPILE ERROR HERE */
};

}

void f1(void){puts("F1 CALLED");return;};
void f2(void){puts("F2 CALLED");return;};
void f3(void){puts("F3 CALLED");return;};
void f4(void){puts("F4 CALLED"); exit(0);};

/* BEGIN new.c */

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

void f1(void);
void f2(void);
void f3(void);
void f4(void);

int main(void)
{
void (*table[])(void) = {
f1, f2, f3, f4
};
void (**p)(void);

p = table;
while (p != table + sizeof table / sizeof *table) {
(*p++)();
}
return 0;
}

void f1(void)
{
puts("F1 CALLED");
}

void f2(void)
{
puts("F2 CALLED");
}

void f3(void)
{
puts("F3 CALLED");
}

void f4(void)
{
puts("F4 CALLED");
}

/* END new.c */
 
U

user923005

Bartc said:
I'm having problems with the following code.
I have a table of function pointers, and a function pointer variable p which
steps through the functions.
But I'm not allowed to increment the variable using ++p.
What's the problem here?
Also, I may not be interested in returning from any of these functions (each
will call the next according to some global variable). Any recommended way
of doing this (throwing away return address) other than a crude asm("pop
R")?


#include <stdio.h>
#include <stdlib.h>
void f1(void);
void f2(void);
void f3(void);
void f4(void);
int main(void)
{
void (*table[])(void)={&f1,&f2,&f3,&f4};    /* table of function pointers */
void (*p)(void);    /* pointer to one of the functions (I hope) */
p=table[0];

while(1)
{ (*p)();    /* Call function @p */
  ++p;    /* COMPILE ERROR HERE */
};

void f1(void){puts("F1 CALLED");return;};
void f2(void){puts("F2 CALLED");return;};
void f3(void){puts("F3 CALLED");return;};
void f4(void){puts("F4 CALLED"); exit(0);};

/* BEGIN new.c */

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

void f1(void);
void f2(void);
void f3(void);
void f4(void);

int main(void)
{
    void (*table[])(void) = {
        f1, f2, f3, f4
    };  
    void (**p)(void);  

    p = table;
    while (p != table + sizeof table / sizeof *table) {
        (*p++)();
    }
    return 0;

}

void f1(void)
{
    puts("F1 CALLED");

}

void f2(void)
{
    puts("F2 CALLED");

}

void f3(void)
{
    puts("F3 CALLED");

}

void f4(void)
{
    puts("F4 CALLED");

}

/* END new.c */

I like to use typedefs for arrays of function pointers.

#include<math.h>
#include<stdio.h>
typedef double (*f_t) (double);
static f_t f[] = {log, log10, sqrt, cos, cosh, exp, sin, sinh, tan,
tanh, 0};
int main(void)
{
int i;
f_t *flist = f;
for (i = 0; f; i++) {
printf("function %d of 0.5 = %g\n", i, f (0.5));
printf("function %d of 0.5 = %g\n", i, (*f) (0.5));
}
while (*flist) {
f_t ff = *flist;
printf("current function of 0.5 = %g\n", ff(0.5));
flist++;
} return 0;
}
 
P

pete

user923005 said:
void (*table[])(void) = {
f1, f2, f3, f4
};
I like to use typedefs for arrays of function pointers.

typedef double (*f_t) (double);
static f_t f[] = {log, log10, sqrt, cos, cosh, exp, sin, sinh, tan,
tanh, 0};
{
f_t ff = *flist;

I've been softening my stance on when to use typedefs lately.
I like them for the e_type interface.
http://www.mindspring.com/~pfilandr/C/e_driver/e_driver.h

I've recently considered that simplefying declarations,
is probably sufficient reason to use a typedef.

I less recently decided that they were OK for struct types.
http://www.mindspring.com/~pfilandr/C/lists_and_files/list_lib.h

I mostly, though not always, avoid using constructs (like typedefs)
that have to be looked up in order to read the code,
and I figured that since a struct type had to be looked up
to really know what it is anyway,
there's not really any harm in using a typedef.
I also use function like macros, which is another exception
to avoiding things that have to be looked up.

Ultimately, it comes down to
"Does this make the code easier to read or not?"
and I haven't formalized my rules for making that determination.
 
B

Ben Pfaff

pete said:
I've been softening my stance on when to use typedefs lately. [...]
I've recently considered that simplefying declarations,
is probably sufficient reason to use a typedef.

I agree.

One special case: I usually use a typedef to declare a function
type that I am going to use for declaring a pointer-to-function.
An extreme example is that I find
typedef void callback_func(int event);
callback_func *set_callback(callback_func *);
much easier to read than the equivalent that does not use a
typedef.
 

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,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top