Sto cercando di capire cosa fa il seguente codice in C?Spiegazione complicata del cast C
((void(*)())buf)();
dove 'BUF' è una matrice char
.
Sto cercando di capire cosa fa il seguente codice in C?Spiegazione complicata del cast C
((void(*)())buf)();
dove 'BUF' è una matrice char
.
Facciamo un passo alla volta.
void(*)()
Questo è un puntatore a una funzione che accetta argomenti non specificati e non ha alcun valore di ritorno.
(void(*)())buf
imposta semplicemente buf a questo tipo di puntatore di funzione. Infine,
((void(*)())buf)();
chiama questa funzione.
Quindi l'intera istruzione è "interpretare buf
come puntatore a una funzione void
senza argomenti e chiamare tale funzione".
Lanciare un buffer di caratteri in una funzione e chiamarlo è malvagio. È un tentativo di modifica del codice, oppure è un intento malevolo fare un qualche tipo di exploit. Ad ogni modo, evitalo a tutti i costi. –
Correggetemi se ho torto, ma non è il valore del puntatore (l'indirizzo dell'array) che viene trattato come una funzione, non il contenuto dell'array? "interpret * il valore * in buf" suona un po 'come stai dicendo che i contenuti sono interpretati come un puntatore a una funzione. –
-1 (non proprio): accetta argomenti non specificati in C – pmg
Inserisce buf
in un puntatore di funzione di tipo void(*)()
(una funzione che restituisce nulla/non valido e che accetta argomenti non specificati) e la chiama.
Lo standard ANSI non consente realmente il cast dei normali puntatori di dati ai puntatori di funzione, ma la piattaforma può consentirlo.
Come mai puoi lanciare un array su un puntatore a funzione ?? C'è qualche articolo che lo spiega? –
Un puntatore è solo una raccolta di byte come qualsiasi altro valore (che può quindi essere presentato in C come una matrice di caratteri). Probabilmente troverai che altrove nel programma è stato eseguito il contrario di questo: 'char * buf = (char *) function;' o qualcosa di simile. – Wernsey
Puoi farlo perché è C - puoi fare quello che vuoi. È una pessima idea, ma puoi farlo. – Clyde
Direi che in molte circostanze, si blocca la macchina. Altrimenti, considera la matrice come un puntatore a una funzione che restituisce nulla e la invoca.
Inserisce buf
in un puntatore a funzione, che accetta argomenti non specificati e lo chiama.
-1 (non proprio): accetta argomenti non specificati in C – pmg
@ pmg, grazie. Ho modificato la risposta. –
Questo lancia buf
al tipo void (*)()
, un puntatore a una funzione che accetta parametri non specificati e non restituisce nulla. Quindi chiama la funzione a quell'indirizzo (le due parentesi più a destra).
-1 (non proprio): accetta argomenti non specificati in C – pmg
@ pmg, buon punto. –
chiama un puntatore a funzione. la funzione non ha argomenti.
((void(*)())buf)(); \------------/ cast `buf` to \---------/ type: pointer to function accepting a fixed but unspecified number of arguments and returning void \----------------/ and call that "function"
+1 Sei corretto sul numero di parametri non specificato. Se avessi chiarito con un esempio, probabilmente avresti ottenuto più apprezzamento per la tua comprensione :) – Andomar
Potreste trovare "esperto c programmazione" una buona lettura - disfare questo tipo di cose è in uno dei capitoli, se ricordo bene. È passato molto tempo da quando l'ho letto, ma ricordo di aver pensato che valesse la pena in quel momento. http://www.amazon.com/Expert-Programming-Peter-van-Linden/dp/0131774298
Tendo ad usare il comando "cdecl" quando mi imbatto in una dichiarazione da capogiro. Esempio:
[[email protected]]$ cdecl
Type `help' or `?' for help
cdecl> explain (void(*)())buf
cast buf into pointer to function returning void
Anche se ci sono casi in cui mi auguro che ci sia uno strumento là fuori che spiega l'uscita di "cdecl":/
Esiste una versione online dello strumento 'cdecl' che lsc menzionato che potresti trovare utile: http://www.cdecl.org/
Cerca un programma chiamato "cdecl". Scaricalo. Incollare la dichiarazione in esso. Sii illuminato –
@Paul: Ci proverò e spero che non uccida la mia macchina! –
Questo codice potrebbe essere ragionevolmente visualizzato in un JIT o nel sistema operativo in un linker/loader dinamico. Come altri hanno già detto, è roba spaventosa, ma solo se l'hai incontrata in un'applicazione tipica. Al suo posto giusto, non è roba spaventosa, solo cose difficili. –