Scaricare la presentazione
La presentazione è in caricamento. Aspetta per favore
1
Unità Didattica 1 Linguaggio C
Fondamenti. Struttura di un programma.
2
La storia del Linguaggio C
UNIX (1969) - DEC PDP-7 Assembly Language BCPL - un OS facilmente accessibile che fornisce potenti strumenti di sviluppo prodotti a partire da BCPL. Si tratta di un assemblatore noioso, lungo ed incline agli errori Un nuovo linguaggio "B" come secondo tentativo (1970) Un linguaggio "C" totalmente nuovo come successore di "B" (1971) Dal 1973 UNIX OS, quasi totalmente scritto in C.
3
La storia del Linguaggio C
E’ stato utilizzato per sviluppare il sistema operativo UNIX, viene comunemente usato per scrivere sistemi operativi Indipendente dall’hardware (portabile) Standardizzazione: inizialmente sono state definite molte piccole varianti del C, incompatibili tra loro; ANSI (American National Standards Institute) si è occupato della sua standardizzazione, nel 1989, standard aggiornato nel 1999.
4
Caratteristiche del C Linguaggio a medio/alto livello. Basso livello di controllo degli errori nella fase di compilazione. Variabili tipizzate, con notevoli possibilità di conversione mediante il type casting, che permette di forzare una variabile a cambiare tipo; Abbina ad un medio-alto livello di astrazione, un buon controllo delle operazioni a basso livello.
5
Fasi di traduzione ed esecuzione di un programma C
Preprocessing: il preprocessore si occupa di includere altri file (es: librerie standard) e sostituisce simboli speciali che seguono particolari direttive (es: costanti simboliche); Compilazione: traduzione del programma in codice oggetto (linguaggio macchina (*.obj)); Linking: risoluzione dei riferimenti a funzioni e variabili definite altrove (es. in librerie standard o definite dall’utente), producendo una immagine eseguibile (progr.exe); Esecuzione: Loading: caricamento in memoria il codice eseguibile; Esecuzione delle istruzioni;
6
Primo programma in C #include <stdio.h> /*# = Preprocessore C
precede le direttive che il compilatore valuta prima di iniziare la traduzione effettiva del programma (in questo caso l’inclusione della libreria delle funzioni standard di I/O (stdio.h)) */ main() /* Funzione principale, l’esecuzione di un programma C consiste nella esecuzione del main */ { printf(“Hello world\n”); /* Visualizza sullo standard output (monitor) la frase fra “ ” \n rappresenta un a capo }
7
Esecuzione Ogni programma comincia la sua esecuzione con la funzione main. I commenti sono inseriti tra i caratteri /* e */ (oppure // per commentare un’intera riga) e vengono ignorati in fase di compilazione. In int main (void), la sintassi indica che il programma non ha argomenti di ingresso e che restituisce un valore intero (che indica la terminazione con successo).
8
Istruzioni e Librerie Il set di istruzioni del C è molto limitato: le primitive più comunemente utilizzate (es. I/O, matematiche) sono contenute nelle librerie standard del C sotto forma di funzioni. Se si utilizzano delle funzioni contenute in una certa libreria, questa deve essere inclusa mediante la direttiva #include del preprocessore. Es: la funzione di output printf() è contenuta della libreria standard stdio.h; Per usare la funzione deve essere presente la direttiva di inclusione: #include <stdio.h>
9
Preprocessore # è il simbolo con cui iniziano i comandi del preprocessore. Tali comandi non sono terminati da “;” Attraverso il preprocessore si esprimono direttive al compilatore; Principali direttive: Definizione delle costanti simboliche e delle macro; Compilazione condizionale del codice.
10
Preprocessore: #include
La direttiva #include: consente di includere in la copia di un file specificato. Esistono due forme: #include <nome_file> viene utilizzata per includere file di intestazione (header file) della libreria standard, che sono memorizzati in directory standard (dipendenti dall’implementazione del compilatore); #include “nome_file” cerca il file nella directory corrente, altrimenti in directory standard (perciò è utilizzata per includere header file definiti dal programmatore).
11
Preprocessore: #define
La direttiva #define è utilizzata per definire costanti simboliche e macro. Il formato è: #define [identificatore] [testo_di_sostituzione] All’interno del file in cui è presente tutte le successive occorrenze dell’identificatore saranno automaticamente sostituite dal testo_di_sostituzione, prima della compilazione.
12
Preprocessore: #define (per definizione di costanti simboliche)
#define PI sostituirà tutte le occorrenze della costante simbolica PI con quella numerica
13
Preprocessore: #define (per definizione di macro)
Le macro possono essere definite con o senza argomenti. Una macro senza argomenti viene elaborata come una costante simbolica. In una macro con argomenti, essi saranno rimpiazzati all’interno del testo di sostituzione e solo in seguito sarà espansa la macro: ovvero, il testo di sostituzione rimpiazzerà la lista degli identificatori e degli argomenti all’interno del programma. Esempio: #define AREA_CERCHIO(x) ( PI * (x) * (x) ) ogni volta che nel programma appare AREA_CERCHIO(r) il valore di r sarà usato al posto di x, la costante PI sarà rimpiazzata dal suo valore (definito precedentemente) e la macro verrà espansa all’interno del programma.
14
Preprocessore: #define (per definizione di macro)
Esempio 1: area = AREA_CERCHIO(4) sarà espanso in area = ( * (4) * (4) ); Esempio 2: area = AREA_CERCHIO(c+2) area = ( * (c+2) * (c+2) ); Vantaggi nell’uso delle macro: risparmio nella definizione di una funzione; miglioramento nella leggibilità del programma.
15
Preprocessore: Compilazione condizionale
Consente al programmatore di controllare la compilazione del codice del programma. Le direttive condizionali del preprocessore vengono valutate come espressioni costanti intere. Esempio: #define DEBUG #ifdef DEBUG printf(“Variabile x = %d\n”, x ); #endif l’istruzione printf viene compilata (ed eseguita) solo nel caso in cui la variabile DEBUG sia definita.
16
Variabili In C ogni variabile è caratterizzata dai seguenti aspetti:
Tipo; Classe di memoria. Assegnare un tipo ad una variabile significa assegnarle il dominio dal quale assume i valori; La classe di memoria determina la durata della vita (ciclo di vita) e l’ambito di visibilità (scope) delle variabili.
17
Tipi di dati Tipi di base – char: carattere – int: intero
– float: virgola mobile, singola precisione – double: virgola mobile, doppia precisione – void: indica che il dominio della variabile è l’insieme vuoto Qualificatori: – unsigned: (es: unsigned int, unsigned char) – short: (es: short int) – long: (es: long int, long double)
18
Dichiarazione di Variabili
[tipo_var] var0, var1, …; E' possibile inizializzare una variabile al momento della dichiarazione: Esempi: int i, j, k=1; float x=2.6, y; char a;
19
Dichiarazione di Costanti
La definizione di identificatori per le costanti, oltre che con il comando di preprocessore #define, può avvenire usando il modificatore const: const tipo nome_costante = valore ; Esempi: const double e = ;
20
Funzioni Generalizzazione del concetto di funzione algebrica:
legge che associa a valori delle variabili in ingresso valori della variabili in uscita o, più in generale, azioni. Raggruppano operazioni che possono essere riutilizzate usando il nome della funzione e i suoi parametri (chiamata della funzione), senza preoccuparsi dell’aspetto implementativo; I programmi in C combinano funzioni definite dal programmatore con funzioni di libreria standard; Una funzione deve essere definita (definizione) e dichiarata (prototipo), prima della definizione, relativamente al nome e ai tipi dei parametri in ingresso e in uscita.
21
Parametri alle funzioni
Una funzione può avere dei parametri in ingresso e un parametro di uscita (tale fatto non rappresenta una limitazione perché si può restituire anche una struttura dati complessa); Se non si vuol restituire alcun valore da una funzione è sufficiente dichiararla di tipo void ed omettere o meno il return; E’ obbligatorio mettere le parentesi () (oppure (void)) dopo il nome della funzione anche se non ci sono parametri in ingresso. void funz(void) oppure: void funz()
22
Parametri alle funzioni
In C i parametri alle funzioni sono sempre passati per valore; Al momento della chiamata, le funzioni allocano (riservano) memoria per le variabili d’ingresso; In ciascuna variabile viene copiato il valore che le viene passato al momento della chiamata.
23
Definizione e prototipo e chiamata di una funzione
#include <stdio.h> [tipoUscita] nomeFunzione([tipo0],[tipo1]); //Prototipo void main() { [tipoUscita] a; [tipo0] x; [tipo1] y; … a = nomeFunzione(x, y); //Chiamata } [tipoUscita] nomeFunzione([tipo0] var0, [tipo1] var1) { //Definizione
24
Esempio di passaggio di parametri: Calcolo della potenza di un numero
#include <stdio.h> int potenza(int, int); //Prototipo void main() { int x, y, z; x = 2; y = 3; z = potenza(x, y); //Chiamata } //Definizione int potenza(int base, int n) { int i, p = 1; for(i = 0; i < n; i++) p = p * base; return (p); x 2 y 3 Passaggio al momento della chiamata base 2 n 3
25
Esempio di passaggio di parametri in funzioni ricorsive
#include <stdio.h> long int fattoriale(int); //Prototipo void main() { long int fatt; int n; scanf(“%d”, &n); fatt = fattoriale(n); } long int fattoriale(int n) if (n == 0) return 1; return (n * fattoriale(n-1));
26
Struttura di un programma C
/* commenti: nome programma, descrizione, etc. */ #istruzioni per il preprocessore dichiarazione di tipi, variabili, costanti; prototipi delle funzioni; tipo_di_ritorno main (lista_argomenti) { dichiarazione variabili locali sequenza di istruzioni } tipo_di_ritorno funzione_1 (lista_argomenti) tipo_di_ritorno funzione_n (lista_argomenti) { … }
27
Scrittura di un programma C su più moduli (file)
Quando si scrivono programmi di grosse dimensioni è consigliabile suddividere i programmi in moduli separati. La funzione main() sarà contenuta in un solo file (es: “mioprogr.c”); E’ buona norma concentrare inclusioni di librerie standard, dichiarazioni e prototipi necessari ad un modulo, in un unico file (header file) da includere in tale modulo (es: #include “mioprogr.h”); Esiste un compromesso fra il desiderio che ogni modulo acceda solo alle informazioni di cui ha bisogno (N moduli => N header file) e la realtà pratica secondo la quale è difficile gestire molti header file; Per programmi di dimensioni ridotte è meglio avere un unico header file contenente le informazioni da condividere fra due punti qualunque del programma scritto su più moduli e includere in essi l’unico header file creato;
28
Scrittura di un programma C su più moduli e un unico header file
#include <mioprogr.h> void main() { … } #include <mioprogr.h> [tipo1] funz3([tipo0] var0) { … } [tipo5] funz2([tipo3] var1) #include <mioprogr.h> [tipo0]funz0([tipo0] var0) { … } [tipo3]funz1([tipo0] var7) mioprogr.c #include <stdio.h> #define … Variabili globali; Prototipi funzioni; mod1.c mod2.c Header file: file, da includere in ogni modulo, contenente inclusione di librerie,dichiarazioni e prototipi. mioprogr.h
29
Classi di Memorizzazione delle Variabili
Variabili locali (automatiche); Variabili globali (esterne);
30
Variabili Locali (o automatiche)
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.
31
Esempi di dichiarazione di variabili automatiche
#include <stdio.h> void main(void) int i, j; … funz(); void funz() int i, j; //Sono variabili automatiche,ovvero //locali alla funzione. Fuori dalla //funz non sono più accessibili, cessano //di esistere (per esempio le due //variabili “i, j” definite nel “main” //sono del tutto scorrelate da queste).
32
Modifica del ciclo di vita di variabili locali
E’ possibile modificare il ciclo di vita di una variabile locale in modo che conservi il suo valore fra l’uscita e il successivo rientro nella funzione o nel blocco nel quale è stata dichiarata; Tale modifica si ottiene anteponendo alle variabili locali la parola chiave static: void funz() static int i, j; //Sono variabili automatiche, ovvero //locali alla funzione. Fuori dalla //funz non sono più accessibili ma al //rientro nella funzione riacquistano //il valore che avevano al momento //dell’uscita dalla funzione stessa.
33
Variabili Globali (o esterne)
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, anche in moduli diversi; 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);
34
Variabili globali in un unico modulo
#include <stdio.h> int i, j; //variabili globali inizializzate a 0 void main(void) extern int i, j; //in questo caso la //dichiarazione viene //generalmente omessa int x; i = 2; j = 3; x = i + j;
35
Variabile globale condivisa in più moduli
#include <stdio.h> extern int i; void funz(void); void funz(void) int j; j = i+1; … #include <stdio.h> int i; void main(void) funz(); mioprogr.c mod1.c i è globale per entrambi i moduli
36
Variabile globale condivisa in più moduli con uso di header file
#include <stdio.h> int i; void funz(void); … mioprogr.h #include “mioprog.h” void funz() int j; j = i+1; … #include “mioprog.h” void main(void) funz(); i è globale per entrambi i moduli (mioprogr.c, mod1.c) mioprogr.c mod1.c
Presentazioni simili
© 2024 SlidePlayer.it Inc.
All rights reserved.