2015-07-24 8 views
5

Können wir eine Funktionsadresse einer bestimmten Signatur in einen Funktionszeiger setzen, der so definiert ist, dass er eine andere Signatur hat und diese nahtlos verwendet?Kann ein Paar Zeiger auf verschiedene Funktionen, die verschiedene Arten von Parametern annehmen, kompatibel sein?

Zum Beispiel den folgenden Code

#include <stdio.h> 

void print_n(int *pn) { 
    printf("%d\n", *pn); 
} 

void print_n_wrapper(void *p) { 
    print_n(p); 
} 

int main(void) { 
    int n = 123; 
    void (*f)(void *) = print_n_wrapper; 
    f(&n); 
    f = print_n; 
    f(&n); 
    return 0; 
} 

wird kompiliert und läuft in meiner Maschine in Ordnung. Rufe ich irgendwie undefiniertes Verhalten auf?

+0

Ja, Sie rufen UB an. Diese Zeigertypen sind nicht kompatibel. –

+0

Es Arbeit finden, aber Compiler sagt Ihnen "Warning: Zuweisung von inkompatiblen Zeigertyp" – LPs

Antwort

8

Ja, es ist undefined behaviour.

Zitiert C11, Kapitel §6.3.2.3, Pointers, (emphasis Mine)

Ein Zeiger auf eine Funktion eines Typs kann auf einen Zeiger auf eine Funktion eines anderen Typs konvertiert werden und wieder zurück; Das Ergebnis muss mit dem ursprünglichen Zeiger verglichen werden. Wenn ein konvertierter Zeiger verwendet wird, um eine Funktion aufzurufen, deren Typ nicht mit dem referenzierten Typ kompatibel ist, ist das Verhalten nicht definiert.

und in Bezug auf die „Funktion, deren Typ nicht kompatibel“ Teil geht die Definition der Kompatibilität wie

Für zwei Funktionstypen kompatibel zu sein, beide kompatibel Rückgabetypen angeben soll. (146) Darüber hinaus müssen die Parametertyplisten, wenn beide vorhanden sind, in der Anzahl der Parameter übereinstimmen und den Ellipsenbegrenzer verwenden. entsprechende Parameter müssen kompatible Typen haben.

Das bedeutet, void * und int *sollten die gleichen Typen haben, aber sie sind nicht . Also, die Funktionen sind auch nicht kompatibel.

+0

OP fragt, ob seine zwei verschiedenen Funktionstypen * kompatibel * sind, so sollte Ihre Antwort gehen, was es bedeutet für Funktionstypen kompatibel sein –

5

Der Aufruf von print_n(p) in print_n_wrapper definiert ist, da alles, was Sie tun, ist eine void* Umwandlung, die ursprünglich zu einem f = print_n;int*

Die Zuordnung einer int* war, wird man Mühe geben. Obwohl die Zuweisung definiert ist, ist das Verhalten beim nachfolgenden Aufruf f(&n) undefined.

Verwandte Themen