2012-11-18 12 views
5

Eventuali duplicati:
Casting a function pointer to another typePassa parametri aggiuntivi tramite il puntatore di funzione legale/definito in C?

assumere i inizializzare un puntatore di funzione con una funzione che prende effettivamente meno parametri quindi la definizione puntatore a funzione, sarà la funzione comunque eseguire correttamente se chiamato attraverso la puntatore di funzione?

Ho provato questo con gcc e ha funzionato come previsto, ma mi chiedo se questo comportamento è coerente tra compilatori/piattaforme (temo che in alcuni ambienti potrebbe devastare sullo stack):

#include <stdio.h> 

typedef void (*myfun)(int, int, int); 

void test_a(int x, int y, int z) { 
    printf("test_a %d %d %d\n", x, y, z); 
} 

void test_b(int x, int y) { 
    printf("test_b %d %d\n", x, y); 
} 

int main() { 
    myfun fp; 
    fp = test_a; 
    fp(1, 2, 3); 
    fp = (myfun) test_b; 
    fp(4, 5, 6); 
} 

risposta

4

Il il comportamento del tuo programma non è definito. Il fatto che compili sia dovuto al cast, che dice in modo efficace al compilatore "questo è sbagliato, ma fallo comunque". Se si rimuove il cast, si otterrà il messaggio di errore appropriato: (. Da gcc -Wall -Werror)

a.c:17:8: error: assignment from incompatible pointer type [-Werror] 

Più in particolare, il comportamento dipende dalle convenzioni di chiamata. Se tu fossi su una piattaforma se gli argomenti fossero passati in ordine "inverso" sullo stack, il programma avrebbe dato un risultato molto diverso.

+1

Si può anche arrestare in modo anomalo se viene utilizzata la pulizia del callee. –

+0

Vedo. Che ne dici di definire il tipo di puntatore della funzione senza lista parametri, come'typedef void (* myfun)() '. Il compilatore dovrebbe garantire che l'ordine dei parametri sullo stack sia "giusto" in quel caso? – Askaga

+0

@BillAskaga No: per "garantire" ciò che si desidera, è necessario assicurarsi che la funzione di destinazione e il puntatore della funzione utilizzino entrambi [convenzione chiamata cdecl] (http://en.wikipedia.org/wiki/X86_calling_conventions#cdecl). – ChrisW

10

È un comportamento non definito. Utilizzare a proprio rischio. Si è detto di causare Nasal Demons!

enter image description here

+0

Questa immagine è fantastica. Qui offro una versione ripulita e una traccia vettoriale: https://www.dropbox.com/sh/c0f5htyg46jcels/AABD9Qaw2JlhMAKCycAek-9ia?dl=0 – wilx

+0

Lol. Grazie.Ho raccontato la storia del comportamento non definito alla mia figlia preferita a cui piace il doodle. Mi ha mandato questo il giorno dopo. C'è semplicemente così tanto da amare a riguardo. – EvilTeach

+0

Ecco il JPG: http://imgur.com/gallery/Zomm1zq/new – wilx

3

La chiamata di funzione è un comportamento non definito.

(C99, 6.3.2.3p8) "[...] Se un puntatore convertito viene utilizzato per chiamare una funzione il cui tipo non è compatibile con il tipo puntato, il comportamento non è definito."

Per informazioni nota che un tipo funzione:

(C99, 6.2.5p20) "[...] descrive una funzione con tipo di ritorno specificato un tipo di funzione è caratterizzata da . il suo tipo di ritorno e il numero e il tipo dei suoi parametri. "

Problemi correlati