4

As I heard, It is not safe to convert pointer to function to void*.

Okay, is it safe to cast

void (*enumerate) (void (*)(const struct foo *event, void *), void *)

to

void (*enumerate) (void (*)(const void *event, void *), void *)

and then call it with

void (*)(const void *, void *) as first argument, which treats its first void* as struct foo*?

rkosegi
  • 14,165
  • 5
  • 50
  • 83
KAction
  • 1,977
  • 15
  • 31
  • @rkosegi Casting a function pointer to `void*` is undefined behavior. There's no guarantee it'll fit. It might work though, if you're lucky. – onemasse Jun 09 '12 at 12:18
  • IIRC, it's not just UB; it's plain forbidden, so a strict compiler would not accept a program that tries (`gcc -Wall -pedantic -Werror` wouldn't). – Fred Foo Jun 09 '12 at 12:21
  • See http://stackoverflow.com/questions/559581/casting-a-function-pointer-to-another-type?rq=1 – rkosegi Jun 09 '12 at 12:22
  • I am not casting function ptr to void*. – KAction Jun 10 '12 at 09:00

1 Answers1

7

No, this is not safe. It's not guaranteed by the C standard that a struct foo * and a void * have the same size and format. In general, casting function pointers to other function pointer types is a recipe for disaster. The safe solution is to insert an extra function that converts the arguments to the right type, just as you'd do when writing a comparison function for qsort that handles non-void * arguments:

static int compare_foo_as_voidp(void const *a, void const *b)
{
    return compare_foo((struct foo const *)a, (struct foo const *)b);
}

(As Oli Charlesworth writes in the comment, the cast itself is not the problem, but calling through the pointer causes UB.)

Fred Foo
  • 355,277
  • 75
  • 744
  • 836
  • +1. However, casting between function pointer types is ok (although silly), so long as you never call the function from the wrong pointer type. – Oliver Charlesworth Jun 09 '12 at 12:24
  • Can you give an example of a version of C which has two different pointer sizes? – Aaron Digulla Jun 09 '12 at 12:28
  • @AaronDigulla - x86 DOS made use of [near and far pointers](http://en.wikipedia.org/wiki/C_memory_model#Pointer%5Fsizes). – Brett Hale Jun 09 '12 at 12:40
  • @AaronDigulla: On a Harvard architecture, code and data live in separate address spaces, so function pointers may well have a different size to object pointers. – Oliver Charlesworth Jun 09 '12 at 12:40
  • @BrettHale: I know but I never wrote DOS code. Would the compiler throw an error when you tried to cast one into the other or just widen/shorten the pointer? – Aaron Digulla Jun 09 '12 at 12:51
  • 1
    @AaronDigulla: when a function is called through a pointer of the wrong type, the compiler will not convert its arguments. – Fred Foo Jun 09 '12 at 12:53
  • But it **is** guaranteed by the C Standard that any pointer to object can be assigned to a `void *` and back without loss of information. – Jens Aug 24 '12 at 19:13