2012-06-09 5 views
3

Comme je l'ai entendu, il n'est pas sûr de convertir le pointeur en fonction void*.Conversion de pointeur de fonction en C

D'accord, est-il sûr de jeter

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

à

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

puis appelez avec

void (*)(const void *, void *) comme premier argument, qui traite son premier vide * comme struct foo *?

+0

@rkosegi Lancer un pointeur de fonction à «void *» est un comportement indéfini. Il n'y a aucune garantie que ça va aller. Cela pourrait fonctionner si vous êtes chanceux. – onemasse

+0

IIRC, ce n'est pas seulement UB; c'est strictement interdit, donc un compilateur strict n'accepterait pas un programme qui essaye ('gcc -Wall -pedantic -Werror' ne le ferait pas). –

+0

Voir http://stackoverflow.com/questions/559581/casting-a-function-pointer-to-another-type?rq=1 – rkosegi

Répondre

7

Non, ce n'est pas sûr. Il n'est pas garanti par le standard C qu'un struct foo * et un void * ont la même taille et le même format. En général, le lancement de pointeurs de fonction vers d'autres types de pointeurs de fonction est une recette de désastre. La solution sûre est d'insérer une fonction supplémentaire qui convertit les arguments du type droit, comme vous le feriez lors de l'écriture d'une fonction de comparaison pour qsort qui gère void * non arguments:

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

(Comme Oli Charlesworth écrit dans le commentaire, la distribution elle-même n'est pas le problème, mais appeler via le pointeur provoque UB.)

+0

Pourquoi la downvote? –

+0

+1. Cependant, la conversion entre les types de pointeurs de fonction est correcte (bien que stupide), tant que vous n'appelez jamais la fonction du mauvais type de pointeur. –

+0

Pouvez-vous donner un exemple d'une version de C qui a deux tailles de pointeur différentes? –