4

I'm trying to use function pointer in my code, the code is as below.

#include <stdio.h>
#include <pthread.h>

typedef void (*PFUNC)(int);

typedef struct tag_FUNC_INFO_S
{
    PFUNC callback;
    int   index;
} FUNC_INFO_S;

PFUNC callback_print(int index)
{
    printf("[callback] index = %d\n", index);
    return NULL;
}

void thread_test(FUNC_INFO_S *info)
{
    info->callback(info->index);

    pthread_exit(NULL);
}

int main()
{
    pthread_t tid;

    FUNC_INFO_S info;
    info.callback = callback_print;
    info.index    = 777;

    pthread_create(&tid, NULL, (void *)thread_test, &info);

    printf("main printing\n");

    return 0;
}

After compiled the code with "gcc -Wall xxx.c -o xxx -lpthread", the compiler complains with the following message:

func_ptr_test.c:30:16: warning: incompatible pointer types assigning to 'PFUNC' (aka 'void ()(int)') from 'PFUNC (int)' (aka 'void ((int))(int)' [-Wincompatible-pointer-types] info.callback = callback_print;

But, if I change the code from

info.callback = callback_print;

to

info.callback = (PFUNC)callback_print;

No warning message comes out any more. But, even without type casting, I think the "info.callback" has totally the same type with "callback_print", so I'm wondering why the warning message comes out. Does anyone have idea about this?

5
  • 3
    I do believe: PFUNC callback_print(int index) --> void callback_print(int index) Commented Jul 2, 2018 at 16:35
  • the functions being used as threads MUST have the syntax: void * functionName( void *) Your thread functions do not have that syntax Commented Jul 3, 2018 at 16:29
  • near the end of the main() function the statement(s): int *status = NULL; pthread_join( tid, &status ); is missing Commented Jul 3, 2018 at 16:35
  • the first few lines of thread_test() should be: void *thread_test( void *param) { FUNC_INFO_S info = *( FUNC_INFO*)param; Commented Jul 3, 2018 at 16:39
  • strongly suggest replacing: gcc -Wall xxx.c -o xxx -lpthread with gcc -Wall -Wextra -Wconversion -pedantic -std=gnu11 xxx.c -o xxx -lpthread Commented Jul 3, 2018 at 16:41

3 Answers 3

4

Sometimes, exploring what is beneath the surface helps to understand the picture better.

In C, you can pretty much treat the function name as a pointer to that function. Take a look at the example below

#include <stdio.h>

int main() {
    (*printf)("test\n");
    return 0;
}

In the code snippet above, we could simply use printf() instead of (*printf)(), and it actually is the usual way you would call a function.

Another example is the signal() library function (yes, I am a FreeBSD user), whose definition is given as

 void
 (*signal(int sig, void (*func)(int)))(int);

When you call signal(), the convention is

void
handle(int sig)
{
    ...
}

int main(int argc, char **argv)
{
    (void) signal(SIGUSR1, handle);
    ...
}

Now, can you see the trick here? Although, signal() is declared to take void (*func)(int) (i.e. a pointer to a function returning void and taking a single int argument), we pass the name of a function of that type as the second argument to signal().

Going back to your question, PFUNC is an alias for a pointer to a function returning void and taking a single int argument. By declaring callback as PFUNC callback you are saying your compiler that, the callback variable will point a function which returns void and takes a single int argument.

So, you should have

void callback_print(int index) /* now you have a void ()(int) */
{
    printf("[callback] index = %d\n", index);
}

to match what is expected as the lvalue of your assignment performed by info.callback = callback_print;.

Sign up to request clarification or add additional context in comments.

Comments

4

You can't define a function with a function pointer typedef. You just need to define the function to match the typedef:

void callback_print(int index)
{
    printf("[callback] index = %d\n", index);
}

Comments

1

You have have a wrong understanding of the funcion pointer.

You can change your

PFUNC callback_print(int index) 

prototype as

void callback_print(int index) 

And all things should be fine. Why the compiler is not happy is because

PFUNC callback_print(int index) 

prototype is void (* (*)(int))(int) but PFUNC type is void(*)(int) So your return type is void(*)(int) not void

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.