Assert.h: differenze tra le versioni

Contenuto cancellato Contenuto aggiunto
Nessun oggetto della modifica
Etichette: Inserimento tag INDEX o altre direttive Modifica da mobile Modifica da web per mobile
m Reverted 1 edit by 185.186.104.242 (talk) to last revision by LauBot (TwinkleGlobal)
Etichette: Annulla Inserimento tag INDEX o altre direttive
Riga 1:
{{Libreria_standard_C}}
{{LIBRERIA-STANDAR-C}}
{{TITOLOtitolo MINUSCOLOminuscolo}}
 
'''ASSETassert.Hh''' Èè Ll'[[HEADERheader FILEfile]] DELLAdella [[LIBRERIAlibreria STANDARDstandard DELdel C]] CHEche DEFINISCEdefinisce LAla MACROmacro <CODEcode>ASSETassert()</CODEcode>. QUESTAQuesta MACROmacro IMPLEMENTAimplementa UNun SISTEMAsistema DIdi controllo CONTROLLO DELLEdelle [[ASSERZIONEasserzione LOGICAlogica|ASSERZIONIasserzioni]], CHE PUÒche ESSEREpuò UTILIZZATOessere utilizzato PERper VERIFICAREverificare Ee CONTROLLAREcontrollare Ll'EVENTUALEeventuale VERIFICARSIverificarsi DIdi CASIcasi "IMPOSSIBILIimpossibili" NELnel PROGRAMMAprogramma.
 
{| CLASSEclass="WIKITABLEwikitable"
|- BGCOLORbgcolor=#E9E9E9 e9e9e9
! NOMENome || DESCRIZIONE Descrizione
|-
|<CODEcode>ASSETassert</CODEcode>|| QUANDOQuando QUESTAquesta MACROmacro VIENEviene ESEGUITAeseguita, ESSAessa COMPUTAcomputa ILil RISULTATOrisultato DELLdell'ESPRESSIONEespressione FRONTALEfornìtale: SEse ESSAessa RISULTArisulta ESSEREessere FALSAfalsa (INin ALTREaltre PAROLEparole, SEse ILil VALOREvalore FINALEfinale RISULTArisulta ESSEREessere 0), <CODEcode>ASSETassert</CODEcode> SCRIVEscrive ALCUNEalcune INFORMAZIONIinformazioni DIdi [[DEBUGdebug]] SUsu <CODEcode>STDERRstderr</CODEcode> Ee, SUCCESSIVAMENTEsuccessivamente, RICHIAMArichiama LAla FUNZIONEfunzione <CODEcode>ABORTabort()</CODEcode>. Le informazioni riportate LEsu INFORMAZIONIstderr RIPORTATE SU STDERR INCLUDONOincludono:
* ILil TESTOtesto DELLdell'ESPRESSIONEespressione CHEche HAha FORNITOfornito ILil RISULTATOrisultato 0
* ILil NOMEnome DELdel FILEfile SORGENTEsorgente (LAla MACROmacro PREDEFINITApredefinita FILE__FILE__)
* il numero della linea in cui si è fallita l'asserzione (la macro predefinita __LINE__)
* IL NUMERO DELLA LINEA IN CUI SI È FALLITA L'ASSERZIONE (LA MACRO PREDEFINITA LINEA
|}
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.
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 IL VALORE DELLA VARIABILE "SCELTA" SIA EFFETTIVAMENTE COMPRESO NEL RANGER VALIDO, NONOSTANTE L'USCITA DAL CICLO WHILE IMPLICITAMENTE AFFERMI LA VERIDICITÀ DI QUESTA CONDIZIONE.
 
INTint SCELTAscelta = 0;
do {
/* VISUALIZZOVisualizzo UNun MENUmenu CONcon 4 SCELTEscelte NUMERATEnumerate da 1 a 4 */
SCANFscanf("%d", &SCELTAscelta);
} WHILEwhile (SCELTAscelta<1 || SCELTAscelta>4);
/* PRIMOPrimo BLOCCOblocco DIdi OPERAZIONIoperazioni ESEGUITEeseguite INin BASEbase ALal VALOREvalore SCELTOscelto */
ASSETassert(SCELTAscelta>=1 && SCELTAscelta <=4);
/* SECONDOSecondo BLOCCOblocco DIdi OPERAZIONIoperazioni ESEGUITE INeseguite in BASEbase ALal VALOREvalore SCELTOscelto */
 
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 />
UTILIZZANDO <CODE>ASSERT()</CODE>, IL PROGRAMMATORE SI ACCERTA NUOVAMENTE CHE LA CONDIZIONE CHE AVEVA PROVOCATO L'USCITA DAL CICLO CICLO WHITE 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 un salvataggio parziale dello stato del programma. Per questo, un codice simile a:
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 PROSEGUIRE L'ESECUZIONE, ALMENO PERMETTERE UN SALVATAGGIO PARZIALE DELLO STATO DEL PROGRAMMA. PER QUESTO, UN CODICE SIMILE A:
 
INTint *PTRptr = MALLOCmalloc(SIZEOFsizeof(INTint) * 10);
ASSERTassert(PTRptr != NULL);
/* UTILIZZOutilizzo DIdi PTRptr */
 
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.
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.
 
QUANDOQuando ILil PROGRAMMATOREprogrammatore NONnon HAha PIÙpiù BISOGNObisogno DELLEdelle ASSERZIONIasserzioni, INVECEinvece DIdi ELIMINARLEeliminarle TUTTEtutte MANUALMENTEmanualmente PUÒpuò DEFINIREdefinire LAla COSTANTEcostante <CODEcode>NDEBUG</CODEcode> PRIMAprima DIdi INCLUDEREincludere NELnel FILEfile SORGENTEsorgente Ll'HEADERheader <CODEcode>ASSERTassert.Hh</CODEcode>: INin QUESTOquesto MODOmodo, LAla MACROmacro <CODEcode>ASSERTassert()</CODEcode> VIENEviene ESPANSAespansa SEMPLICEMENTEsemplicemente in:
##DEFINEdefine ASSERTassert(IGNOREignore)((VOIDvoid) 0)
eliminando quindi tutte le possibili interazioni con il programma. Bisogna quindi far notare che, in questo caso, l'espressione passata ad <code>assert()</code> non viene valutata. Come espressioni inserite all'interno di <code>assert()</code> vanno quindi assolutamente evitate quelle con effetti collaterali, come ad esempio
ELIMINANDO QUINDI TUTTE LE POSSIBILI INTERAZIONI CON IL PROGRAMMA. BISOGNA QUINDI FAR NOTARE CHE, IN
ASSERT assert(*Ii++);
QUESTO CASO, L'ESPRESSIONE PASSATA AD <CODE>ASSERT()</CODE> NON VIENE VALUTATA. COME ESPRESSIONI INSERITE ALL'INTERNO DI <CODE>ASSERT()</CODE> VANNO QUINDI ASSOLUTAMENTE EVITATE QUELLE CON EFFETTI COLLATERALI, COME AD ESEMPIO
che finirebbero per 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.
ASSERT(*I++);
CHE FINIREBBERO PER 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'INSERZIONE, 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.
 
== Voci correlate ==