C pointer to multiple functions - c

I want to pass to a function a pointer that can point to one of several functions.
What is the syntax for this?
void func_a(char c){
//
}
void func_b(char c){
//
}
void receiver(void (*function_pointer)()
{
// do stuff with the pointer to the function, e.g. call it:
function_pointer('a');
function_pointer('b');
function_pointer('c');
}
void main(){
receiver(&func_a); // calls func_a with 'a', then 'b', then 'c'
receiver(&func_b); // calls func_b with 'a', then 'b', then 'c'
}
Will the above work as expected? I assume a function pointer can only be used for functions with the same signature?

Yes, that looks like it should work.
And yes, you can only use the single pointer for functions sharing a signature.
Minor notes:
You don't need to use & to take the address of a function, the function's name evaluates to its address in suitable contexts.
Functions that are local and only intended to be used as callbacks (func_a() and func_b()) should be declared as static.

One thing you can do to make this cleaner is use a typedef. Define your function pointer in a typedef and you can use it in the arguments. Also you don't need the &. Example with your code.
#include <stdio.h>
static void func_a(char c)
{
printf("a:%c\n", c);
}
static void func_b(char c)
{
printf("b:%c\n", c);
}
typedef void (*function)(char c);
void receiver( function func )
{
func('a');
func('b');
func('c');
}
void main()
{
receiver(func_a);
receiver(func_b);
}
I learned this from 'learn C the hard way' link: http://c.learncodethehardway.org/book/ex18.html

Function pointer to select one function among multiple functions
#include <stdio.h>
int plus(int a,int b){return a+b;}
int minus(int a,int b){return a-b;}
int multiply(int a,int b){return a*b;}
int divide(int a,int b){return a/b;}
int percentage(int a,int b){return a%b;}
void gec(int(**p)(int ,int),int c)
{
c=c%5;
if(c==0)
*p=plus;
else if(c==1)
*p=minus;
else if(c==2)
*p=multiply;
else if(c==3)
*p=divide;
else
*p=percentage;
}
int main(void) {
int a=100,b=20,c=12,r;
int(*fptr)(int,int)=NULL;
gec(&fptr,c);
r=(*fptr)(a,b);
printf("%d",r);
return 0;
}

Related

Merging two similar c functions into one

I have two functions that look like the ones down below and I am trying to merge the two with a function called function3 however I don't want it to check the parameter 'function' everytime it enters the while loop as it is a very poor way to do it. I am wondering if I can merge the two with only one if statement.
void function1(){
int value,a,b;
while(condition){
value=a*b;
}
}
void function2(){
int value,a,b;
while(condition){
value=a+b;
}
}
//merge two functions
void function3(int function){
int value,a,b
while(condition){
if(function==1){
value=a*b;
}
else{
value=a+b;
}
}
}
It is not clear from the code you posted what you intent to do, since you don't actually do anything with the values you calculated.
Aside, I think that you are looking for an array of functions or an array of pointers to functions.
You can use the variable function to access the function that you need, assuming it matches the array index of that function.
int function1(int a, int b) {
return a * b;
}
int function2(int a, int b) {
return a + b;
}
int (*f[])(int, int) = { function1, function2 };
void call_function(int function, int a, int b) {
// check that "function" is within bounds of the array
if (function < 0 || function >= sizeof(f) / sizeof(f[0])) {
// handle out of bounds
}
// call appropriate function
int ret_val = f[function](a, b);
return;
}

How to create a function from other 3 with the same signature in C

I'm working with C, and I'm trying to build a kind of "composite" function, by joining 2 functions with the same signature, and a third with almost the same signature but just one less argument. The functions should be executed in sequence, but the final function must have the same signature. You can think it as building a function with code blocks using same signature(I have it implemented in C++ with policy class, but I'm trying a C approach as the rest of the code is in C already).
I built some code very simple, just to explain my approach.
#include <stdio.h>
#include <stdlib.h>
typedef void simulFileProc(int a, int b);
typedef void simulRead(int a);
typedef struct compFunct{
simulFileProc* file1;
simulRead* read;
simulFileProc* file2;
} compFunct;
void realProc(int a, int b){
printf("call from realProc %d, %d\n",a,b);
}
void realRead(int a){
printf("call from read %d\n",a);
}
simulFileProc* join(int a, int b, compFunct* func){
void sf(int a, int b){
func->file1(a,b);
printf("intermediate line\n");
func->read(a);
func->file2(a,b);
}
return &sf;
}
int main() {
compFunct* c = malloc(sizeof(256));
c->file1 = &realProc;
c->read = &realRead;
c->file2 = &realProc;
int a=0;
int b=0;
simulFileProc* s = join(a,b,c);
s(4,3);
return 0;
}
It is working, but for some reason, just the first function print.
call from realProc 4, 3
intermediate line
If I comment the line "func->read(a);", I have a segmentation fault.
What is wrong ?? Is there a smarter way to do ?

Is this a correct way to pass a function into a struct?

I looked but couldn't find a direct reference for this question. I'm new to function pointers (and C), so I don't know all the tricks one can do yet :)
I've effectively got a function:
void select_comparator(My_Struct *structure, int (*comp)(int x, int y)) {
...
...where My_Struct has prototype:
typedef struct my_struct {
int (*comp)(int x, int y);
} My_Struct;
Modulo some minor details. I just want to know if the following is correct syntax:
void select_comparator(My_Struct *structure, int (*comp)(int x, int y)) {
structure->comp = comp;
}
It seems almost too easy, and I'm worried it is.
Nothing's wrong: this is the basis of callbacks in c. Just make sure the signature of your function pointer matches the type defined in your structure. Where it gets remotely tricky is when you're using this in a large project, and people forget to check if the function pointer is valid or void, along with arguments, etc.
Code Listing
/*******************************************************************************
* Preprocessor directives.
******************************************************************************/
#include <stdio.h>
/*******************************************************************************
* Data types.
******************************************************************************/
typedef struct my_struct {
int (*comp)(int x, int y);
} My_Struct;
/*******************************************************************************
* Function prototypes.
******************************************************************************/
int c(int a, int b);
void select_comparator(My_Struct *structure, int (*comp)(int x, int y));
/*******************************************************************************
* Function definitions.
******************************************************************************/
/*----------------------------------------------------------------------------*/
int main(void)
{
My_Struct s;
select_comparator(&s, &c);
s.comp(1, 2);
return 0;
}
/*----------------------------------------------------------------------------*/
void select_comparator(My_Struct *structure, int (*comp)(int x, int y))
{
structure->comp = comp;
}
/*----------------------------------------------------------------------------*/
int c(int a, int b)
{
int ret = 0;
if (a < b) {
ret = (-1);
} else if (a > b) {
ret = 1;
}
return ret;
}
The code is ok.
Though note that function pointers have plain horrible syntax in C, particularly when passed to/returned from functions. Try writing something like "function returning function-pointer and taking function-pointer as parameter" and you'll soon realize that the syntax is pure madness.
It is therefore a good idea to make function pointers "fall in line" with the rest of the language by using typedefs.
You code could be written like this:
typedef int comp_t (int x, int y); // typedef a function type
typedef struct {
comp_t* comp; // pointer to such a function type
} My_Struct;
void select_comparator(My_Struct *structure, comp_t* comp) {
structure->comp = comp;
}
Now the code turns easier to read and the function pointer behaves pretty much like any other pointer.

Use case of function pointers in c

One of the common use cases I've come across when I read about function pointers is that they can be used to make a function more flexible, as part of the functionality of the function can be taken in as a parameter. An example for this is qsort where I can make a compare function to decide what is meant by greater and lesser (ascending, descending, is a multiple of,etc) and pass the compare funtion pointer to qsort function.
Here, the function repeat has addptr as parameter and therefore performs multiplication.
int add(int a, int b)
{
return a+b;
}
int (*addptr)(int,int);
int repeat(int a,int b,int (*funcptr)(int,int))
{
int i,ans=0;
for(i=0;i<a;i++)
{
ans=(*funcptr)(ans,b);
}
return ans;
}
int main()
{
addptr=&add;
printf("%d\n",repeat(7,5,addptr));
return 0;
}
But the same exact thing can be done without function pointers at all!
int add(int a, int b)
{
return a+b;
}
int repeat(int a,int b,int func(int,int))
{
int i,ans=0;
for(i=0;i<a;i++)
{
ans=func(ans,b);
}
return ans;
}
int main()
{
printf("%d\n",repeat(7,5,add));
return 0;
}
So why is this even one of the uses of function pointers?
What is the advantage of the first code over the second?
There is a rule C11 6.7.6.3/8 saying that if you write a function inside a parameter list, it will get adjusted to a pointer to function of that type:
A declaration of a parameter as ‘‘function returning type’’ shall be
adjusted to ‘‘pointer to function returning type’’,
This works similar to when you write an array as function parameter, it gets adjusted to a pointer to the first element.
That being said, it is not really meaningful to write a function as a parameter, it is just very confusing to the reader. Use function pointers instead.
EDIT
For maximum readability, I would personally recommend using this style:
typedef int operation_t (int, int);
int repeat (int a, int b, operation_t* operation)
{ ...
Though the most commonly used style is perhaps this one:
typedef int (*operation_t) (int, int);
int repeat (int a, int b, operation_t operation)
{ ...
I prefer the former since hiding pointers behind typedefs is a bad idea, and since that style makes function pointers consistent with regular pointers.
As noticed in comment by #user2390668, func in repeat in already a function pointer. And when you call it, add decays to a function pointer.
If your question is what is a possible use case for a variable holding a function pointer, we must try to imagine a use case where a function will not only be passed as a parameter, but will have to be stored. An example for that would be simulating polymorphism of structs in C. Here is an oversimplified example:
#include <stdio.h>
struct Base {
/* common member variables
...
*/
const char *name;
void (*display)(void *, FILE *fd);
};
struct S1 {
struct Base base;
/* other member variables */
};
void _S1_display(void *this, FILE *fd) {
struct S1 *s1 = this;
fprintf(fd, "In S1, name: %s\n", s1->base.name);
}
struct S2 {
struct Base base;
/* other member variables */
};
void _S2_display(void *this, FILE *fd) {
struct S2 *s2 = this;
fprintf(fd, "In S1, name: %s\n", s2->base.name);
}
void process(void *this, FILE *fd) {
struct Base *base = this; /* valid because base is first element of both S1 and S2 */
base->display(this, fd);
}
int main() {
struct S1 s1 = { "s1", &_S1_display };
struct S2 s2 = { "s2", &_S2_display };
process(&s1, stdout);
process(&s2, stdout);
return 0;
}
Ok, fur such a simply example, polymorphism would not be necessary, but as I said it is oversimplified...
You may use pointers to functions when you need a little more abstraction.
For example, you may want to manage a table of operators that a generic function should use:
int add(int a, int b) {
return a+b;
}
int sub(int a, int b) {
return a-b;
}
int mult(int a, int b) {
return a*b;
}
int div(int a, int b) {
return a/b;
}
void doit(int a,int b,int (*ptr[2])(int,int)) {
printf("%d\n",ptr[0](a,b));
printf("%d\n",ptr[1](a,b));
}
int main() {
int (*ptr[2])(int,int);
printf("additives (1) or multiplicatives (2) ?");
int choice;
scanf("%d",&choice);
switch(choice) {
case 1:
ptr[0] = &add;
ptr[1] = ⊂
break;
default:
ptr[0] = &mult;
ptr[1] = &div;
break;
}
doit(7,5,ptr);
return 0;
}
Of course you can also design a doit function with two pointers but sometimes a table is more convenient (think about a variable length table of function pointers for example, I know even in this case we may use a variable arguments list...).
At least, passing a function pointer in parameter is defining a function pointer variable...
Another example is also implementing in C object oriented programming, where you may implement methods as function pointers members.

Getting a sub-function to modify variables

This is a simple test program where I am trying to get the func function to modify the variables a and b which are then used in the main function. Is there a way to get func to return the modified variables so they can be used? (preferably without using struct as I don't understand how it works)
#include <stdio.h>
void func(int a, int b)
{
a=a+1;
b=b+1;
}
void main(void)
{
int a=0, b=0;
while (1)
{
func(a,b);
printf("%d\n",a);
}
}
If you want to modify variables in the calling function, you have to pass their address to func (i.e. pass a pointer to these variables
void func(int* a, int* b)
{
*a=*a+1;
*b=*b+1;
}
func(&a,&b);
Your code passes its arguments by value. This means that a and b are copied into new variables which are initialised with the values of the calling variables but only exist for the duration of func.
I agree. The best way to do this is using pointers. But are you aware that your code will never terminate? You should use a condition that can end excution of the while loop.
Also, if you wanna perfom the exact same action to both variables you could just use the return statement like this:
#include <stdio.h>
void func(int a, int b)
{
return a+1;
}
void main(void)
{
int a=0, b=0;
while (a < 5)
{
func(a);
func(b);
printf("%d\n",a);
}
}
We can achieve through pointers . Don't use While(1) because it will go to infinite loop. I think following program help to you.
#include <stdio.h>
void func(int* a, int* b)
{
*a=*a+1;
*b=*b+1;
}
void main(void)
{
int a=0, b=0;
//while (1)
// {
func(&a,&b);
printf("%d\n",a);
// }
}

Resources