7
void funcPtr(int a);

int main(){
   int k=1;
   void (*funcPtr2)(int);

   funcPtr2 = (void*)(funcPtr);
   // funcPtr2 = (void(*)(int))(funcPtr);

   (*funcPtr2)(k);
   return 0;
}

void funcPtr(int a){
   printf("%d", a);
}

What is the difference between (void*) and (void(*)(argument type) in function pointer type casting?

As a result, it does not occur warning.

Is this wrong? about (void*) type casting

C Goldsworthy
  • 334
  • 2
  • 12
양진혁
  • 81
  • 4

3 Answers3

7

Is this wrong? about (void*) type casting

Yes, it is.

C standard doesn't allow a conversion of a function pointer to an object pointer or assignment between them. If you up your compiler warning level, you may get warnings/errors such as compiling with:

gcc -Wall -Wextra -pedantic-errors -std=c11 file.c

I am not sure why you thought about casting a function pointer. Provided the function pointer type matches the function, simply assign it:

 funcPtr2 = funcPtr;

Aside:

You can use the function pointer just like a function:

 funcPtr2(k);

and use a standard prototype for main such as:

int main(void)
P.P
  • 117,907
  • 20
  • 175
  • 238
  • The restriction to disallow code <-> data pointer conversion dates back to the days of the Intel Memory Model (http://en.wikipedia.org/wiki/Intel_Memory_Model) and probably similar contraptions on other architectures. E.g. under the "medium" model, `sizeof(void *) == 2`, but `sizeof(void(*)(void)) == 4`, making to and from conversions unsafe. Of course, none of these platforms and memory models have any relevance regarding POSIX. – Arne Vogel Jun 01 '15 at 13:18
1

This is an issue with dlsym, declared void *dlsym(void *restrict handle, const char *restrict name). dlsym returns a pointer to a function named name defined in and accessible through handle.
However, as @BlueMoon states, this is not defined in ISO C and gcc indeed complains if made pedantic. POSIX tried to address that and required conforming implementation to make that cast well-defined in its indefiniteness.

From POSIX

Note that conversion from a void * pointer to a function pointer as in:

fptr = (int (*)(int))dlsym(handle, "my_function");

is not defined by the ISO C standard. This standard requires this conversion to work correctly on conforming implementations.

Another way to make that cast conforming is to first convert the function pointer to void** and then dereference it. This should be well-defined. In your case,

void funcPtr(int a); /* symbol to extract */

int main(void)
{
     void (*fn)(int);
     *(void**)(&fn) = dlsym(your_handle, "funcPtr");


     fn(5);
}
Community
  • 1
  • 1
edmz
  • 8,220
  • 2
  • 26
  • 45
0
(void*)

casts a pointer to a pointer to void, or a generic pointer.

void(*)(int)

is a function pointer to a function taking an int argument and returning nothing.

int fn(float f) { return f * 3.14; }

void* ptr = fn;

Would make ptr the address of the first machine instruction of fn but not allow you to use it.

int(*ptr)(float) = fn;
// or
typedef int(FnPtr)(float);
FnPtr* ptr = fn;

takes the address in a way that the compiler knows what kind of function call is being pointed to so that you can call the function

int n = ptr(2.5);

Which can be useful for doing something like

void get_data(int socket, int timeout, void(*callback)(char*, size_t));

Which is a function I can pass another function to.

void recv_data(char* data, size_t len)
{
    ...
}

...

get_data(socket, 60, recv_data);
undur_gongor
  • 15,657
  • 5
  • 63
  • 75
kfsone
  • 23,617
  • 2
  • 42
  • 74