Appunti per Scuola e Università
humanisticheUmanistiche
Appunti e tesine di tutte le materie per gli studenti delle scuole medie riguardanti le materie umanistiche: dall'italiano alla storia riguardanti le materie umanistiche: dall'italiano alla storia 
sceintificheScientifiche
Appunti, analisi, compresione per le scuole medie suddivisi per materie scientifiche, per ognuna troverai appunti, dispense, esercitazioni, tesi e riassunti in download.
tecnicheTecniche
Gli appunti, le tesine e riassunti di tecnica amministrativa, ingegneria tecnico, costruzione. Tutti gli appunti di AppuntiMania.com gratis!
Appunti
informatica
CComputerDatabaseInternetJava
Linux unixReti


AppuntiMania.com » Informatica » Appunti di c » Le costanti

Le costanti




Visite: 1346Gradito:apreciate 4-stela [ Medio appunti ]
Leggi anche appunti:

Le variabili


Le variabili E' il momento di ripescare CIAO.C e complicarlo un poco. #include

Contenuto del floppy disk


Contenuto del floppy disk Il floppy disk allegato costituisce una raccolta di

L'i/o e la gestione dei file


L'I/O e la gestione dei file Per Input/Output (I/O) si intende l'insieme delle
immagine di categoria

Scarica gratis Le costanti

Le costanti

Le costanti, in senso lato, sono dati che il programma non può modificare. Una costante è, ad esempio, la sequenza di caratteri 'Ciao Ciao!n' vista in precedenza: per la precisione, si tratta di una costante stringa. Essa non può essere modificata perché non le è associato alcun nome simbolico a cui fare riferimento in un'operazione di assegnazione. Una costante è un valore esplicito, che può essere assegnato ad una variabile, ma al quale non può essere mai assegnato un valore diverso da quello iniziale.

Ad esempio, una costante di tipo character (carattere) è un singolo carattere racchiuso tra apici.

char c1, c2 = 'A';

c1 = 'b';

c2 = c1;

'c' = c2;      //ERRORE! impossibile assegnare un valore a una costante

Una costante intera con segno è un numero intero:

int unIntero = 245, interoNegativo = -44;

Una costante intera senza segno è un numero intero seguito dalla lettera U, maisucola o minuscola, come ci insegna il nostro CIAO2.C

unsigned int anni = 31U;

Per esprimere una costante di tipo long occorre posporle la lettera L, maiuscola o minuscola

long abitanti = 987553L;

Omettere la L non è un reato grave il compilatore segnala con un warning che la costante è long e procede tranquillamente. In effetti, questo è l'atteggiamento tipico del compilatore C: quando qualcosa non è chiaro tenta di risolvere da sé l'ambiguità, e si limita a segnalare al programmatore di avere incontrato qualcosa di poco convincente. Il compilatore C 'presume' che il programmatore sappia quel che sta facendo e non si immischia nelle ambiguità logiche più di quanto sia strettamente indispensabile.

Una U (o u) individua una costante unsigned; le costanti unsigned long sono identificate, ovviamente, da entrambe le lettere UL, maiuscole o minuscole, in qualsivoglia ordine. Le costanti appartenenti ai tipi integral possono essere espresse sia in notazione decimale (come in tutti gli esempi visti finora), sia in notazione esadecimale (anteponendo i caratteri 0x o 0X al valore) sia in notazione ottale (anteponendo uno  al valore).

char beep = 07;          // ottale; 7

unsigned long uLong = 12UL; // decimale; 12 unsigned long

unsigned maxUInt = 0xFFFFU; // esadecimale; 65535 unsigned

Una costante di tipo floating point in doppia precisione (double) può essere espressa sia in notazione decimale che in notazione esponenziale: in questo caso si scrive la mantissa seguita dalla lettera E maiuscola o minuscola, a sua volta seguita dall'esponente. Per indicare che la costante è in singola precisione (float), occorre posporle la lettera F, maiuscola o minuscola. Per specificare una costante long double occorre la lettera L

float varF = 1.0F;

double varD = 1.0;

double varD_2 = 1.; // lo 0 dopo il punto decimale puo' essere omesso

long double varLD = 1.0L; // non e' un long int! C'e' il punto decimale!

double varD_3 = 2.34E-2; // 0.0234

Dagli esempi si deduce immediatamente che la virgola è espressa, secondo la convenzione anglosassone, con il punto ('

Il C non riconosce le stringhe come tipo di dato, ma ammette l'utilizzo di costanti stringa (seppure con qualche limite, di cui si dirà): esse sono sequenze di caratteri racchiuse tra virgolette, come si è visto in più occasioni. Quanti byte occupa una stringa? Il numero dei caratteri che la compongono più uno (pag.  ). In effetti le stringhe sono sempre chiuse da un byte avente valore zero binario , detto terminatore di stringa. Il NULL finale è generato automaticamente dal compilatore, non deve essere specificato esplicitamente.

Attenzione: le sequenze di caratteri particolari, come 'n', sono considerate un solo carattere (ed occupano un solo byte). I caratteri che non rientrano tra quelli presenti sulla tastiera possono essere rappresentati con una backslash (barra inversa) seguita da una 'x' e dal codice ASCII esadecimale a due cifre del carattere stesso. Ad esempio, la stringa 'x07x0Dx0A' contiene un 'beep' (il carattere ASCII 7) e un ritorno a capo (i caratteri ASCII 13 e 10, questi ultimi equivalenti alla sequenza 'n

I codici ASCII possono essere utilizzati anche per esprimere un singolo carattere:

char beep = 'x07';

E' del tutto equivalente assegnare ad una variabile char un valore decimale, ottale o esadecimale o, ancora, il valore espresso con x tra apici. Attenzione, però: la rappresentazione ASCII di un carattere è cosa ben diversa dal suo valore ASCII; 0x07 e 'x07' sono tra loro equivalenti, ma diversi da 

La differenza tra un singolo carattere rispetto ad una stringa di un solo carattere sta negli apici, che sostistuiscono le virgolette. Inoltre, 'x07' occupa un solo byte, mentre 'x07' ne occupa due, uno per il carattere ASCII 7 e uno per il NULL che chiude ogni stringa.

Non esistono costanti di tipo void

Le costanti manifeste

Supponiamo di scrivere un programma per la gestione dei conti correnti bancari. E' noto (e se non lo era ve lo dico io) che nei calcoli finanziari la durata dell'anno è assunta pari a 360 giorni. Nel sorgente del programma si potrebbero perciò incontrare calcoli come il seguente:

interesse = importo * giorniDeposito * tassoUnitario / 360;

il quale impiega, quale divisore, la costante intera 

E' verosimile che nel programma la costante  compaia più volte, in diversi contesti (principalmente in formule di calcolo finanziario). Se in futuro fosse necessario modificare il valore della costante (una nuova normativa legale potrebbe imporre di assumere la durata dell'anno finanziario pari a 365 giorni) dovremmo ricercare tutte le occorrenze della costante  ed effettuare la sostituzione con  . In un sorgente di poche righe tutto ciò non rappresenterebbe certo un guaio, ma immaginando un codice di diverse migliaia di righe suddivise in un certo numero di file sorgenti, con qualche centinaio di occorrenze della costante, è facile prevedere quanto gravoso potrebbe rivelarsi il compito, e quanto grande sarebbe la possibilità di non riuscire a portarlo a termine senza errori.

Il preprocessore C consente di aggirare l'ostacolo mediante la direttiva #define , che associa tra loro due sequenze di caratteri in modo tale che, prima della compilazione ed in modo del tutto automatico, ad ogni occorrenza della prima (detta manifest constant) è sostituita la seconda.

Il nome della costante manifesta ha inizio col primo carattere non‑blank che segue la direttiva #define e termina con il carattere che precede il primo successivo non‑spazio; tutto quanto segue quest'ultimo è considerato stringa di sostituzione.

Complicato? Solo in apparenza

#define    GG_ANNO_FIN 360 //durata in giorni dell'anno finanziario




interesse = importo * giorniDeposito * tassoUnitario / GG_ANNO_FIN;

L'esempio appena visto risolve il nostro problema: modificando la direttiva #define in modo che al posto del  compaia il  e ricompilando il programma, la sostituzione viene effettuata automaticamente in tutte le righe in cui compare GG_ANNO_FIN

Va sottolineato che la direttiva #define non crea una variabile, né è associata ad un tipo di dato particolare: essa informa semplicemente il preprocessore che la costante manifesta, ogniqualvolta compaia nel sorgente in fase di compilazione, deve essere rimpiazzata con la stringa di sostituzione. Gli esempi che seguono forniscono ulteriori chiarimenti: in essi sono definite costanti manifeste che rappresentano, rispettivamente, una costante stringa, una costante in virgola mobile, un carattere esadecimale e una costante long integer, ancora esadecimale.

#define    NOME_PROG 'Conto 1.0' //nome del programma

#define    PI_GRECO 3.14 //pi greco arrotondato

#define    RETURN 0x0D //ritorno a capo

#define    VIDEO_ADDRESS 0xB8000000L //indirizzo del buffer video

Le costanti manifeste possono essere definite utilizzando altre costanti manifeste, purché definite in precedenza:

#define    N_PAG_VIDEO 8 //numero di pagine video disponibili

#define    DIM_PAG_VIDEO 4000 //4000 bytes in ogni pagina video

#define    VIDEO_MEMORY (N_PAG_VIDEO * DIM_PAG_VIDEO) //spazio memoria video

Una direttiva #define può essere suddivisa in più righe fisiche mediante l'uso della backslash

#define    VIDEO_MEMORY

(N_PAG_VIDEO * DIM_PAG_VIDEO)

L'uso delle maiuscole nelle costanti manifeste non è obbligatorio; esso tuttavia è assai diffuso in quanto consente di individuarle più facilmente nella lettura dei sorgenti.

Come tutte le direttive al preprocessore, anche la #define non si chiude mai con il punto e virgola (un eventuale punto e virgola verrebbe inesorabilmente considerato parte della stringa di sostituzione); inoltre il crosshatch (' ', cancelletto) deve trovarsi in prima colonna.

La direttiva #define, implementando una vera e propria tecnica di sostituzione degli argomenti, consente di definire, quali costanti manifeste, vere e proprie formule, dette macro, indipendenti dai tipi di dato coinvolti:

#define    min(a,b) ((a < b) ? a : b) // macro per il calcolo del minimo tra due

Come si vede, nella macro min(a,b) non è data alcuna indicazione circa il tipo di ab: essa utilizza l'operatore , che può essere applicato ad ogni tipo di dato . Il programmatore è perciò libero di utilizzarla in qualunque contesto.

Le macro costituiscono dunque uno strumento molto potente, ma anche pericoloso: in primo luogo, la mancanza di controlli (da parte del compilatore) sui tipi di dato può impedire che siano segnalate incongruenze logiche di un certo rilievo (sommare le pere alle mele, come si dice). In secondo luogo, le macro prestano il fianco ai cosiddetti side‑effect , o effetti collaterali. Il C implementa un particolare operatore, detto di autoincremento , che accresce di una unità il valore della variabile a cui è anteposto: se applicato a uno dei parametri coinvolti nella macro, esso viene applicato più volte al parametro, producendo risultati indesiderati:

int var1, var2;

int minimo;




minimo = min(++var1, var2);

La macrosotituzione effettuata dal preprocessore trasforma l'ultima riga dell'esempio nella seguente:

minimo = ((++var1 < var2) ? ++var1 : var2);

E' facile vedere che esso si limita a sostituire alla macro min la definizione data con la #define, sostituendo altresì i parametri a e b con i simboli utilizzati al loro posto nella riga di codice, cioè ++var1 e var2. In tal modo var1 è incrementata due volte se dopo il primo incremento essa risulta ancora minore di var2, una sola volta nel caso opposto. Se min() fosse una funzione il problema non potrebbe verificarsi (una chiamata a funzione non è una semplice sostituzione di stringhe, ma un'operazione tradotta in linguaggio macchina dal compilatore seguendo precise regole); tuttavia una funzione non accetterebbe indifferentemente argomenti di vario tipo, e occorrerebbe definire funzioni diverse per effettuare confronti, di volta in volta, tra integer, tra floating point, e così via. Un altro esempio di effetto collaterale è discusso a pag. 

Diamo un'occhiata all'esempio che segue:

#define  PROG_NAME 'PROVA'


printf(PROG_NAME);


#undef  PROG_NAME


printf(PROG_NAME); // Errore! PROG_NAME non esiste piu'

Quando una definizione generata con una #define non serve più, la si può annullare con la direttiva #undef . Ogni riferimento alla definizione annullata, successivamente inserito nel programma, dà luogo ad una segnalazione di errore da parte del compilatore.

Da notare che PROG_NAME è passata a printf() senza porla tra virgolette, in quanto esse sono già parte della stringa di sostituzione, come si può vedere nell'esempio. Se si fossero utilizzate le virgolette, printf() avrebbe scritto PROG_NAME e non PROVA: il preprocessore, infatti, ignora tutto quanto è racchiuso tra virgolette o apici. In altre parole, esso non ficca il naso nelle costanti stringa e in quelle di tipo carattere.

Vale la pena di citare anche la direttiva #ifdef#else#endif , che consente di includere o escludere dalla compilazione un parte di codice, a seconda che sia, o meno, definita una determinata costante manifesta:

#define DEBUG


#ifdef DEBUG

// questa parte del sorgente e' compilata

#else

// questa no (lo sarebbe se NON fosse definita DEBUG)

#endif

La direttiva #ifndef e' analoga alla #ifdef, ma lavora con logica inversa:

#define DEBUG


#ifndef DEBUG

// questa parte del sorgente NON e' compilata

#else

. // questa si (NON lo sarebbe se NON fosse definita DEBUG)

#endif

Le direttive #ifdef e #ifndef risultano particolarmente utili per scrivere codice portabile (vedere pag.  ): le parti di sorgente differenti in dipendenza dal compilatore, dal sistema o dalla macchina possono essere escluse o incluse nella compilazione con la semplice definizione di una costante manifesta in testa al sorgente.

Le costanti simboliche

E' di recente diffusione, tra i programmatori C, la tendenza a limitare quanto più possibile l'uso delle costanti manifeste, in parte proprio per evitare la possibilità di effetti collaterali, ma anche per considerazioni relative alla logica della programmazione: le costanti manifeste creano problemi in fase di debugging , poiché non è possibile sapere dove esse si trovino nella memoria dell'elaboratore (come tutte le costanti, non hanno indirizzo conoscibile); inoltre non sempre è possibile distinguere a prima vista una costante manifesta da una variabile, se non rintracciando la #define (l'uso delle maiuscole e minuscole è libero tanto nelle costanti manifeste quanto nei nomi di variabili, pertanto nulla garantisce che un simbolo espresso interamente con caratteri maiuscoli sia effettivamente una costante manifesta).

Il C consente di definire delle costanti simboliche dichiarandole come vere e proprie variabili, ma anteponendo al dichiaratore di tipo la parola chiave const. Ecco un paio di esempi:

const int  ggAnnoFin = 360;

const char return = 0x0D;

E' facile vedere che si tratta di dichiarazioni del tutto analoghe a quelle di variabili; tuttavia la presenza di const forza il compilatore a considerare costante il valore contenuto nell'area di memoria associata al nome simbolico. Il compilatore segnala come illegale qualsiasi tentativo di modificare il valore di una costante, pertanto ogni costante dichiarata mediante const deve essere inizializzata contestualmente alla dichiarazione stessa.

const int unIntCostante = 14;




unIntCostante = 26; //errore: non si puo' modificare il valore di una costante

Il principale vantaggio offerto da const è che risulta possibile accedere (in sola lettura) al valore delle costanti così dichiarate mediante l'indirizzo delle medesime (come accade per tutte le aree di memoria associate a nomi simbolici): ancora una volta rimandiamo gli approfondimenti alla trattazione dei puntatori (pag. 

Infine, le costanti simboliche possono essere gestite dai debugger proprio come se fossero variabili.




 E' preferibile utilizzare la L maiuscola, poiché, nella lettura dei listati, quella minuscola può facilmente essere scambiata con la cifra 

 Nel senso che tutti i suoi 8 bit sono impostati a zero; non va confuso col carattere 

 Le espressioni di controllo generate da un carattere preceduto dalla backslash sono anche dette sequenze ANSI.

 Per non‑blank o non‑spazio si intende qualsiasi carattere diverso da spazi bianchi e tabulazioni.

 Degli operatori C parleremo diffusamente a pag.  e seguenti. Il significato di può essere, per il momento, dedotto dall'esempio. Per ora merita attenzione il fatto che molti compilatori implementano max() e min() proprio come macro, definite in uno dei file .H di libreria.

 Anche l'operatore, , verrà descritto ampiamente (pag. 

 La fase, cioè, di ricerca e correzione degli errori di programmazione. Questa è effettuata con l'aiuto di sofisticati programmi, detti debuggers, che sono spesso in grado di visualizzare il contenuto delle variabili associandovi il nome simbolico; cosa peraltro impossibile con le costanti manifeste, che ne sono prive.

Scarica gratis Le costanti
Appunti su:



Scarica 100% gratis e , tesine, riassunti



Registrati ora

Password dimenticata?
  • Appunti superiori
  • In questa sezione troverai sunti esame, dispense, appunti universitari, esercitazioni e tesi, suddivisi per le principali facoltà.
  • Università
  • Appunti, dispense, esercitazioni, riassunti direttamente dalla tua aula Universitaria
  • all'Informatica
  • Introduzione all'Informatica, Information and Comunication Tecnology, componenti del computer, software, hardware ...