0

What the hell is this? How is this allowed and legal? I swear, every time I think I'm getting a grip of how this language works, some real cute looking syntax like this shows up.

This is from Semtech's example project for one of their radios.

From within radio.h:

   void    ( *SetRxConfig )( RadioModems_t modem, uint32_t bandwidth,
                              uint32_t datarate, uint8_t coderate,
                              uint32_t bandwidthAfc, uint16_t preambleLen,
                              uint16_t symbTimeout, bool fixLen,
                              uint8_t payloadLen,
                              bool crcOn, bool FreqHopOn, uint8_t HopPeriod,
                              bool iqInverted, bool rxContinuous );

If there's justice in Heaven, how is it OK to write something like this? What is this chunk of code doing and what is it called so I can look up more about it?

testname123
  • 1,061
  • 3
  • 20
  • 43

1 Answers1

3

This declares a function:

int foo(int, float, double);

And this defines (or declares - depending on context) a function pointer, that can be assigned the address of function foo:

int (*function_pointer)(int, float, double);

This is what you are seeing here.

A more verbose explanation with additional examples on how to use, pass as argument and return function pointers can be found in an answer to a similar question suggested by user2357112.

Possible uses include:

  • A library defines hooks to it's function where you can make it call your code. Either by defining a global variable (like void * (*mymegalib_malloc)(size_t size) where you can replace the allocator by your own), or by providing setter functions for the function pointer like in signal,
  • Passing a function to do stuff to another function, like in qsort, where you pass an array, the number of elements and a function, that compares two indices of that array - giving you the opportunity to let qsort operate on whatever data structure you want,
  • Creating some jump tables, like this:

    struct jmp {
        char op;
        double (*func)(double a, double b);
    } jtable = {
        { '+', add },
        { '-', sub },
        { '*', mul },
        { '/', div },
        { 0, NUUL },
    };
    // in some function:
    for (size_t i = 0; jtable[i].op; ++i) {
        if (jtable[i].op == requested_op) {
            result = jtable[i].func(a, b);
        }
    }
    
Community
  • 1
  • 1
Bodo Thiesen
  • 2,476
  • 18
  • 32
  • 1
    Why would you ever want to do this? – testname123 Dec 04 '16 at 23:30
  • "And this defines a function pointer" - without further context, this is a declaration. We cannot know if it is also a definition. – too honest for this site Dec 04 '16 at 23:33
  • 1
    @Olaf: `int foo(int, float, double);` always only declares a function. `int (*function_pointer)(int, float, double);` however can declare (e.g. in a struct or argument list) or define (e.g. in file or function scope) a function pointer. I defined it to define a function pointer, this narrows down the places, where I expect this construct to show up. – Bodo Thiesen Dec 04 '16 at 23:47
  • It it **always** a declaration, regardless if it is also a definition. But it is only a definition for variables with block-scope. And your `struct` is not a defintion at all, but a _type-specifier_ in the first place (specifically a _struct-or-union-specifier_), and forms a _declaration_ without _declarator_. Feel free to read the standard, if you want to use the correct terms. Btw.: what is an "argument list"? This does not exist in C. – too honest for this site Dec 05 '16 at 00:19
  • I talk english not standardish. – Bodo Thiesen Dec 05 '16 at 00:50
  • this is what two wizards fighting looks like. – testname123 Dec 05 '16 at 00:53