简体   繁体   中英

Add a parameter to a function pointer

I'm using a function pointer to delegate states in C.

// states
void state1(int first, int second) {
    ...
}

void state2(int first, int second) {
    ...
}

// state pointer
void (*current_state)(int, int);

// state logic
if (condition1) {
    current_state = &state_1;
} else if (condition2) {
    current_state = &state_2;
}

// do the thing
(*current_state)(1, 2);

Now I'm at a point where the given arguments no longer suffice, so there is a third argument needed. Since I don't want to change all states, I wondered if it is possible to pass a quasi constant parameter along with the pointer. Something like this:

void state3(int first, int second, int third) {
    ...
}

// state logic
...
else if (condition3) {
    // calculate the constant third argument
    int param3 = 0;

    current_state = &state_3(int, int, param3);
}

I there a way to get this to work?

Well I'm not sure I'd recommend it but you could do this sort of thing:

#include    <stdlib.h>
#include    <stdio.h>
typedef int pfun();
int alice( int a, int b)        { return b; }
int bob( int a, int b, int c)   { return c;     }

int main( )
{
pfun*   f;
    f = alice;
    printf( "%d\n", f( 1, 2, 3));
    f = bob;
    printf( "%d\n", f( 1, 2, 3));

    return EXIT_SUCCESS;
}

This compiles with

gcc -o funp -Wall  funp.c

without warnings and runs correctly.

The point is that a function declaration like

int f();

Says that f is a function that returns an int, with unspecified arguments. The downside is that the compiler cannot check that the arguments are of the correct type.

You could pass a *void pointer and cast it to the concrete type in the state function. All state functions will have the same signature. Something like this:

// states
struct state1_args {
    int first;
    int second;
};

struct state2_args {
    float first;
    float second;
    float third;
};

void state1(void* state_args) {
    struct state1_args* args = (struct state1_args*)state_args;
    use(args->first);
    ...
}

void state2(void* state_args) {
    struct state2_args* args = (struct state2_args*)state_args;
    use(args->third);
    ...
}

// state pointer
void (*current_state)(void*);

// state logic
if (condition1) {
    current_state = &state_1;
    current_state_args = &args_1;
} else if (condition2) {
    current_state = &state_2;
    current_state_args = &args_2;
}

// do the thing
(*current_state)(current_state_args);

Wtih the same signature of your

// state pointer
void (*current_state)(int, int);

It is not possible. You have to change your state signature or some how remove an argument from state3.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM