Non c'è motivo per questo. Un modo comune per cui i programmatori scrivono tali macro è perché hanno un codice con istruzioni a ritorno multiplo (che dovrebbero essere evitate se possibile), ma a volte non è semplicemente ragionevole evitarlo). Esempio:
// Bad code
err_t func (void)
{
err_t err;
...
if(err == error1)
{
cleanup();
return err;
}
...
if(err == error2)
{
cleanup();
return err;
}
cleanup();
return err;
}
Fare in modo che la pulizia di tutta la funzione sia una cattiva pratica, a causa della ripetizione del codice.
L'antico modo di risolvere il problema in modo più pulito sarebbe "su errore goto", in cui si inserisce un'etichetta alla fine della funzione. E fai pulizia e torna solo lì. In realtà sarebbe una soluzione un po 'accettabile, ma goto è un tabù, quindi le persone se ne allontanano. Invece sono venuti fuori con qualcosa di simile:
// Slightly less bad code
#define RETURN_FROM_FUNCTION(err) { cleanup(); return (err); }
err_t func (void)
{
err_t err;
...
if(err == error1)
{
RETURN_FROM_FUNCTION(err);
}
...
if(err == error2)
{
RETURN_FROM_FUNCTION(err);
}
RETURN_FROM_FUNCTION(err);
}
Questo rimuove il codice ripetizione, quindi il programma è più sicuro e più facile da mantenere. Questa è probabilmente la risposta alla tua domanda.
Ma questa macro non è ancora una buona soluzione, perché rende il codice più difficile da leggere, perché i programmatori C sono bravi a leggere C, ma sono pessimi leggendo il "linguaggio della casa, il linguaggio macro segreto". E naturalmente ci sono le solite preoccupazioni con i macro: tipo sicurezza, difficile da debug/maintain ecc.
Tuttavia, tutti i metodi sopra menzionati (incluso on-error-goto) provengono da un'incapacità di pensare fuori dagli schemi . La soluzione ottimale è questa:
// proper code
err_t func (void)
{
err_t err;
allocate(); // allocate whatever needs to be allocated
err = func_internal();
cleanup(); // one single place for clean-up
return err;
}
static err_t func_internal (void) // local file scope, private function
{
err_t err;
...
allocate_if_needed(); // or maybe allocation needs to be here, based on results
...
if(if(err == error1)
{
return err;
}
...
if(err == error2)
{
return err;
}
return err;
}
Un 'define' può essere facilmente modificato per fare qualcosa di diverso, come ad esempio l'uscita di un messaggio di errore,' exit' immediatamente, o anche non fare nulla. – usr2564301
se questo è un vecchio codice (non hai specificato C o C++) #define sarebbe stato di fatto il modo delle funzioni inline –
@imsoconfused Le funzioni inline non possono ottenere l'effetto di un'istruzione 'return', però. – aschepler