Function pointer difficulty in C, int (*foo(enum int var))(int)

Viewed 78

Looking at some OSCORE code here: https://github.com/Fraunhofer-AISEC/uoscore-uedhoc/blob/main/modules/oscore/src/option.c and at lines 31 and 63 there is some unusual casting and pointer function work I could use help with.

bool (*class_to_condition(enum option_class class))(uint16_t code)
{
    switch (class) {
    case CLASS_I:
        return is_class_i;       //is_class_x() returns bool
    case CLASS_E:
        return is_class_e;
    default:
        break;
    }
    return false;
}

and later

bool (*condition)(uint16_t) = class_to_condition(class);

then used as

if (!condition(code)) {

I get:

  • class_to_condition(u16) will return a bool
  • "condition" variable is a pointer to a the function class_to_condition, and this function will accept one argument
  • uint16_t is the argument type the function accepts

I don't get

  • the enum
  • why it appears to take two arguments (sort of)
  • Why is the function definition a pointer it self
  • uint16_t "code" is never used in the class_to_condition() ?

Is this so much more efficient as a pointer over the obvious non-pointer alternative that it's worth the increased complexity (clever vs cute)?

3 Answers

The function class_to_condition takes an enum option_class as an argument and returns a function pointer. The function pointer being returned points to a function that has a uint16_t argument and returns a bool.

If we added the following typedef:

typedef bool (*fptr)(uint16_t);

We could rewrite the function signature as:

fptr class_to_condition(enum option_class class) {

And the call as:

fptr condition = class_to_condition(class);

The class_to_condition function takes one argument of type enum option_class. It returns a pointer to a function which takes one uint16_t argument and returns a bool.

Using type-aliases would make it much clearer:

// Declare a -alias of a function pointer
typedef bool (*condition_function_type)(uint16_t);

condition_function_type class_to_condition(enum option_class class)
{
    // ...
}

// ...

condition_function_type condition = class_to_condition(class);

The clockwise/spiral rule could be helpful in decipher complex declarations.

As an addition to the @Someprogrammerdude answer, I would not personally hide the pointer behind the typedef

typedef bool condition_function_type(uint16_t);

condition_function_type *class_to_condition(enum option_class class)
{
    // ...
}

// ...

condition_function_type *condition = class_to_condition(class);

IMO it is much easier to read and understand that we are dealing with function pointers.

Related