C/Appendice/Librerie standard/assert.h: differenze tra le versioni

Contenuto cancellato Contenuto aggiunto
Nessun oggetto della modifica
Nessun oggetto della modifica
Riga 5:
! Nome || Descrizione
|-
|<code>void assert(int expression)</code>|| Quando questa macro viene eseguita, essa computa il risultato dell'espressione fornìtale: se essa risulta essere falsa (in altre parole, se il valore finale risulta essere 0), <code>assert</code> scrive alcune informazioni di debug su <code>stderr</code> e, successivamente, richiama la funzione <code>abort()</code>. Le informazioni riportate su stderr includono:
* il testo dell'espressione che ha fornito il risultato 0
* il nome del file sorgente (la macro predefinita __FILE__)
Riga 11:
|}
L'utilità della macro <code>assert()</code> risiede nella semplicità con la quale si può verificare un'affermazione che si ritiene, in un dato contesto, banalmente ovvia: ad esempio, ricontrollare il valore di una variabile sulla quale si sono già effettuate delle verifiche. Nel codice che segue, la macro <code>assert()</code> viene utilizzata per controllare che il valore della variabile "scelta" sia effettivamente compreso nel range valido, nonostante l'uscita dal ciclo while implicitamente affermi la veridicità di questa condizione.
<source lang="c">
 
int scelta = 0;
Riga 26:
/* Secondo blocco di operazioni eseguite in base al valore scelto */
</source>
 
Utilizzando <code>assert()</code>, il programmatore si accerta nuovamente che la condizione che aveva provocato l'uscita dal ciclo while sia ancora vera: in questo caso, ad esempio, verifica di non aver accidentalmente modificato il valore della variabile <code>scelta</code> all'interno del primo blocco di operazioni.<br>
L'utilizzo di <code>assert()</code> dovrebbe essere limitato alla sola fase di sviluppo di un programma: per la brutalità del metodo di chiusura dell'eseguibile e per la scarsezza di informazioni sull'errore fornite a video, risulterebbe abbastanza frustrante per l'utente finale se utilizzato nella versione definitiva di un applicativo. Buona programmazione vorrebbe, infatti, che venga spiegato all'utente quale causa abbia scatenato il problema e, nel caso non fosse possibile proseguirne l'esecuzione, almeno permettere una salvataggio parziale dello stato del programma. Per questo, un codice simile a:
<source lang="c">
 
int *ptr = malloc(sizeof(int) * 10);
assert(ptr != NULL);
/* utilizzo di ptr */
</source>
 
non rappresenta un uso ottimale di <code>assert()</code>, perché, anche se raramente, è possibile che un'[[allocazione dinamica della memoria|allocazione dinamica di memoria]] fallisca.
 
Quando il programmatore non ha più bisogno delle asserzioni, invece di eliminarle tutte manualmente può definire la costante <code>NDEBUG</code> prima di includere nel file sorgente l'header <code>assert.h</code>: in questo modo, la macro <code>assert()</code> viene espansa semplicemente in:
<source lang="c"> #define assert(ignore)((void) 0) </source>
eliminando quindi tutte le possibili interazioni con il programma. Bisogna però far notare che, in questo caso, l'espressione passata ad <code>assert()</code> non viene valutata: eventuali espressioni con effetti collaterali, come ad esempio
<source lang="c"> assert(*i++);</source>
potrebbero modificare la logica del programma a seconda della definizione o meno della costante <code>NDEBUG</code>. In questo esempio, infatti, al termine della verifica dell'asserzione, il valore del puntatore <code>i</code> risulterebbe incrementato di una unità nel caso <code>NDEBUG</code> non sia definito, mentre resterebbe inalterato nel caso opposto.