35

I have come across the line of code shown below.

I think it may be a cast to a function pointer that returns void and takes a void pointer. Is that correct?

(void (*)(void *))SGENT_1_calc
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Toby
  • 9,696
  • 16
  • 68
  • 132

4 Answers4

46

Yes, it is correct. I find that not very readable, so I suggest declaring the signature of the function to be pointed:

 typedef void sigrout_t(void*);

I also have the coding convention that types ending with rout_t are such types for functions signatures. You might name it otherwise, since _t is a suffix reserved by POSIX.

Later on I am casting, perhaps to call it like

 ((sigrout_t*) SGENT_1_calc) (someptr);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • On the one hand, the typedef removes the necessity for redundant and confusing (at least, to some) brackets. On the other, it reduces the ability to determine immediately what the cast is to. If you want to find out that the cast is to a function pointer, you have to look up what sigrout_t is defined as... +1 for providing the alternative. – autistic Apr 04 '13 at 09:59
  • Names ending in _t are reserved for POSIX, see http://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html – satur9nine Feb 09 '15 at 17:13
10

Yes, it is. The function should be looking like this

void func(void*);

But the statement is missing a target, since a cast to nothing is useless. So it should be like

func = (void (*)(void *))SGENT_1_calc;
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
bash.d
  • 13,029
  • 3
  • 29
  • 42
2

None of the existing answers show it in direct usage, that is, taking a function pointer and casting it in order to call the function. I was playing with this to show the content of my object as json, accessing both the function and the data through anonymous pointers:

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

typedef struct box1_s{
    int a;
    char b[50];
}box1_t;

void box1_t_print(void* ptr){
    box1_t* box = (box1_t*)ptr;
    printf("{\"a\": %i, \"b\": \"%s\"}", box->a, box->b);
}

int main(){
    void* print = (void*)box1_t_print;
    box1_t mybox = {3, "Hi folks, it's me!"};
    void* ptr = &mybox;
    printf("mybox = ");
    ((void (*)(void*))print)(ptr);
    return 0;
}

Output of the program:

mybox = {"a": 3, "b": "Hi folks, it's me!"}

Qwert Yuiop
  • 105
  • 1
  • 11
  • This example appears to actually define a pointer to void, casts a function that takes void and returns a C++ string to plain void and assigns it to the pointer and then casts that pointer back to a function that takes void and returns a C++ string to call it, meaning that this sample does not use the cast that was asked about. Additionally this example uses C++, while the question is tagged as `C`, which is a different language. – Toby Oct 09 '22 at 13:35
  • @Toby My bad, I didn't notice it was tagged as C. I've edited my answer to reflect the question better. – Qwert Yuiop Oct 09 '22 at 14:19
  • With the edit, this is now a valid answer imo. – Toby Oct 12 '22 at 11:57
0

Yes, this is a function pointer cast.

Function pointer casts

To help you with casting functions to pointers, you can define an alias for a function pointer type as follows:

typedef void void_to_void_fct(void*);

You can also define a type for a function that takes and returns values:

typedef int math_operator(int, int);

Later, you can store a function into a function pointer type like this:

void mystery(void* arg) {
    // do something nasty with the given argument
};

int add(int a, int b) {
    return a + b;
}

void_to_void  *ptr1 = mystery;
math_operator *ptr2 = add;

Sometimes, you have a function like print_str :

void print_str(char* str) {
    printf("%s", str);
}

and you want to store it in your function pointer that is agnostic to the argument type. You can then use a cast like this:

(void (*)(void *))print_str

or

(void_to_void_fct*)print_str

Why do we use function pointers?

Function pointers allow you to "store a function" inside a variable (indeed, you store the address of the function). This is very convenient when you want to allow some code to have diferent behavior depending on user input.

For exemple, suppose we have some data and some way to decode it. We could have the following structure to keep this information:

typedef char* decoder_type(char*);
struct encoded_data {
    char*           data;
    decoder_type    *decoder_fct;
};

char* decoding_function_1(char* data) {
//...

char* decoding_function_2(char* data) {
//...

This allows storing both the data and the function to later use them together to decode the data.

Toby
  • 9,696
  • 16
  • 68
  • 132
Jeremy Cochoy
  • 2,480
  • 2
  • 24
  • 39