Esercitazione Visibilità di variabili e funzioni Calcolatori elettronici II Prof. A. Mazzeo Dott. Sara Romano Il linguaggio C • E’ un linguaggio di programmazione che segue il paradigma della programmazione imperativa; • Svolge le operazioni in modo sequenziale (esecuzione delle istruzioni dall'alto verso il basso); • E’ un linguaggio a medio livello (è considerato il linguaggio di più basso livello tra quelli di alto livello); • E’ ampiamente utilizzato per programmare driver, sistemi operativi o comunque applicazioni che richiedono un controllo diretto sulle periferiche. Wikibooks http://it.wikibooks.org/wiki/C I programmi C • Il linguaggio C utilizza i file come contenitori di programmi; • Un programma C è costituito da un insieme di “oggetti” che possono appartenere a due categorie distinte: – Funzioni; – Variabili. • A questi oggetti viene assegnato un nome nel punto in cui vengono definiti nel programma; • Il modo in cui i nomi sono usati per accedere a tali elementi (visibilità) da un determinato punto nel programma è disciplinato da regole (linkage). http://publications.gbdirect.co.uk/c_book Le funzioni • Le funzioni sono i moduli di programma; • Sono sempre esterne, non possono essere definite all’interno di altre funzioni; • Il main è una funzione speciale: – Deve essere unica all’interno del programma; – È la funzione che viene eseguita all’avvio del programma. Struttura dei programmi C Struttura generale di un programma C Compilazione • La compilazione di un programma C si compone in due fasi: traduzione in codice oggetto e produzione dell’eseguibile. Il linker • Il linker raccoglie i file-oggetto e crea il file eseguibile; • Per fare questo ha bisogno di collegare i riferimenti incrociati a simboli di variabili e funzioni. • Esempio: se nel file File1.o si fa riferimento alla funzione f() dichiarata nel file File2.o, nel programma risultante tale riferimento deve essere risolto con degli indirizzi appropriati. Visibilità degli oggetti • Gli oggetti in C possono essere: – Interni – Esterni • La distinzione tra i due ha a che fare con le funzioni: ogni oggetto dichiarato esternamente alla funzione viene detto esterno, altrimenti viene detto interno. • Le funzioni sono tutte esterne (nessuna funzione può essere dichiarata all’interno di un’altra funzione). Linkage • L’accessibilità degli oggetti (tra diversi file o all’interno dello stesso file) viene definita come linkage. • Tre tipi possibili: – External linkage; – Internal linkage; – No linkage. • Gli argomenti e le variabili interne alle funzioni sono prive di linkage Campo di azione nel file sorgente • Il file sorgente, che si ottiene dalla compilazione, è suddiviso in componenti costituite essenzialmente dalla dichiarazione di variabili e di funzioni (prototipi inclusi). • L'ordine in cui appaiono queste componenti determina la visibilità reciproca (si può accedere solo a quello che è già stato dichiarato). External linkage • Gli oggetti con external linkage sono al livello più esterno del programma. Questo tipo di linkage si applica alle funzioni e a tutto ciò che viene dichiarato all’esterno delle funzioni. • Tutte le istanze con un nome che hanno external linkage si riferiscono allo stesso oggetto nel programma. Internal linkage • Questo tipo di linkage viene utilizzato per dichiarare oggetti visibili solo all’interno del file dove sono dichiarati e non nell’intero programma. • I nomi con internal linkage si riferiscono soltanto all’oggetto all’interno del file sorgente. Variabili locali • Parola chiave auto o nessuna dichiarazione; • Sono interne ad un blocco individuato da {…} (es: interne ad una funzione); • Scope (ambito di visibilità): – visibili (accessibili) solo all’interno del blocco di definizione; • Ciclo di vita: – create al momento della dichiarazione, cessano di esistere quando si esce dal blocco; • Sono inizializzate con valori casuali. • Non mantengono il valore tra due riferimenti successivi a meno che non si usa la keyword static. Esempio di variabili locali #include <stdio.h> void main(void) { int i, j; … funz(); } void funz() { int i; static int j; } i e j sono variabili automatiche, ovvero locali alla funzione main e funz. Sono create al momento della dichiarazione e cessano di esistere quando si esce dal blocco. variabile locale che conserva il suo valore fra l’uscita e il successivo rientro nella funzione in cui è stata dichiarata Variabili esterne (globali) • Sono dichiarate una sola volta esternamente a qualsiasi blocco; • Devono essere rese note alle funzioni o ad altri moduli tramite la parola chiave extern (eccetto il caso in cui la dichiarazione preceda la funzione o il blocco in uno stesso modulo (es: all’inizio di un modulo, come avviene nella pratica)). • Scope (ambito di visibilità): – Se rese note ad un blocco con l’uso di extern: ovunque nel programma; – Se rese note ad un blocco senza l’uso di extern: ovunque, nello stesso modulo, a partire dalla loro dichiarazione in avanti; • Ciclo di vita: – Esistono e conservano il loro valore ovunque siano visibili all’interno del programma (es: uscita e successivo rientro da funzioni o blocchi); Esempio: unico file #include <stdio.h> int i, j; void main(void) { extern int i, j; int x; i = 2; j = 3; x = i + j; } Variabili globali. In questo caso la dichiarazione può essere omessa Esempio: diversi file File1.c .... main() {...} int a=0; extern int b; extern double f3(...) {...} File2.c .... int b=0; static int k=1; double f3(...) {...} int f1(...) {...} float f2(...) {...} La funzione main non ha visibilità degli oggetti a, b, f1, f2 e f3. L’oggetto a è visto e riferibile da f1 e f2. La variabile b, k e la funzione f3 sono definite nel file2.c La variabile k è “privata” per il file2.c nel senso che è globale per i soli moduli del file in cui è dichiarata. Dichiarazione e definizione • Dichiarazione di una variabile: rende note le proprietà di tale oggetto (principalmente il suo tipo); • Definizione di una variabile: rende note le proprietà e provoca l’allocazione di un’area di memoria riservata a quella variabile. Tra tutti i file che costituiscono il programma, uno solo deve contenere la definizione di una variabile esterna. Definizione di i e j Dichiarazione di i e j int i; float j; extern int i; extern float j; funz(..) {...} funz3(..) {...} Esercitazione • ARM Project Manager Creazione codice sorgente File C di esempio int a = 3; int b = 5; extern int c; extern int d; extern int sommaNumeri(int,int); int main(void) { int risultato; risultato=sommaNumeri(a,b); return 0; } Scope.c int c=16; static int d=15; int sommaNumeri (int a, int b){ static int x; x=12; return a+b; } Scope2.c Salvataggio del codice sorgente Creazione progetto Aggiungere i file al progetto Opzione compilatore Build project File del progetto Scope.c int a = 3; int b = 5; extern int c; extern int d; int sommaNumeri (int, int); int main(void) { int risultato; risultato=sommaNumeri(a,b); return 0; } Scope.s Inizializzazione a=3 e b=5 A e b sono variabili globali e possono essere utilizzate da altri object file IMPORT / EXPORT • IMPORT symbol • La direttiva IMPORT fornisce un collegamento tra l’oggetto etichettato con symbol (che è definito in un object file separato) e l’object file in cui vi è tale direttiva. Il collegamento viene risolto dal linker. • EXPORT symbol • La direttiva EXPORT dichiara che l’oggetto etichettato con symbol può essere utilizzato a link time da altri object file. Scope2.c int c=16; static int d = 15; int sommaNumeri (int a, int b){ int static x; x=12; return a+b; } Scope2.s Inizializzazione c=16 e d=15 c è globale mentre d è statica Esecuzione con il Debug Indirizzo base dell’area dati Esempio variabili locali int a = 3; extern int c; extern int d; int sommaNumeri (int, int); int main(void) { int b = 5; int risultato; risultato=sommaNumeri(a,b); return 0; } Scope.c Esempio: se utilizzo d? int a = 3; int b = 5; extern int c; extern int d; int sommaNumeri (int, int); int main(void) { int risultato; risultato=sommaNumeri(a,d); return 0; } Scope.c int c=16; static int d = 15; int sommaNumeri (int a, int b){ int static x; x=12; return a+b; } Scope2.c