La presentazione è in caricamento. Aspetta per favore

La presentazione è in caricamento. Aspetta per favore

Introduzione al C Davide Gadia.

Presentazioni simili


Presentazione sul tema: "Introduzione al C Davide Gadia."— Transcript della presentazione:

1 Introduzione al C Davide Gadia

2 I linguaggi di programmazione
Linguaggi Compilati - La scrittura del codice può avvenire tramite un editor di testo, oppure attraverso dei tool IDE. - Una volta creato il codice viene controllato e compilato generando un file in codice macchina. - Il file in codice macchina cosi realizzato può essere eseguito. Vantaggi :: prestazioni ottime, estendibile Svantaggi :: comprensione non immediata Linguaggi Interpretati - Una volta creato il codice esso viene interpretato ed eseguito senza essere tradotto in linguaggio macchina. Vantaggi :: alta portabilità, facilità di programmazione Svantaggi :: lentezza di esecuzione, poco espandibile/versatile Programmazione Grafica aa2006/2007

3 Programmazione Grafica aa2006/2007
Il linguaggio C Caratteristiche - Linguaggio Compilato - Dimensioni codice/eseguibile ridotte - Efficienza di esecuzione dei programmi - Multi-platform - E’ un linguaggio di alto/basso livello - Allocazione dinamica della memoria - Estensione ad oggetti -> C++ Perchè lo abbiamo scelto? - Gestione a tutti i livelli di ogni periferica della macchina - Presenza di librerie per quasi ogni tipo di problema - SDK sviluppati in C/C++ - In PG, la programmazione più spinta e a basso livello viene eseguita generando codice C/C++ - Documentazione molto ampia per ogni tipo di problematica - Il core del codice se ben programmato può essere portato su qualsiasi piattaforma Programmazione Grafica aa2006/2007

4 Workflow di un programma C
Codice Sorgente Compilazione Linking Esecuzione Debug - Stesura del codice - Compilazione - Linking - Debugging - Esecuzione Programmazione Grafica aa2006/2007

5 Compilazione e Linking
Compilazione Statica - elaborazione del file sorgente dal parte del preprocessore, al quale si possono dare delle direttive - generazione del codice assembler - generazione del file oggetto - linking dei vari file oggetto per ottenere il file eseguibile Linking Dinamico - verifica che i simboli/funzioni usati nel codice siano definiti all'interno delle librerie - viene solo trascritta la dipendenza (nome e versione) all'interno dell'eseguibile I vantaggi sono - minori dimensioni effettive dell'eseguibile su disco e in memoria - superiore o pari velocità di caricamento ed esecuzione - aggiornando con versioni più ottimizzate delle lib dinamiche si ottimizzano automaticamente tutti gli eseguibili Programmazione Grafica aa2006/2007

6 Struttura di un programma C
- Comandi di prepocessore Serie di comandi che permettono di comandare il compilatore secondo le proprie esigenze. - Definizione dei tipi Ad ogni variabile deve essere associato un tipo, è una regola per ogni LDP. - Prototipi (Dichiarazione) Dichiarazione dei tipi delle funzioni e delle variabili passate alle funzioni - Variabili (Globali) Variabili disponibili e allocate durante l’intera esecuzione del programma. - Funzioni (Implementazione) Implementazione del core delle funzioni - Main Function Il Main la prima funzione che fa da start (init) ad un programma C. Programmazione Grafica aa2006/2007

7 Programmazione Grafica aa2006/2007
Primo programma Step 1 :: Stesura del codice int main(void) { return 0; } Il vostro codice C dovrà contenere una e una sola funzione main(). 1 int main(void) { printf(“Corso di PG\n”); return(0); } Evolviamo il nostro codice sopra scritto in una forma poco più complessa. 2 Programmazione Grafica aa2006/2007

8 Programmazione Grafica aa2006/2007
Primo programma Step 2 :: Compilazione A seconda su quale SO volete creare il vostro codice sorgente, esistono una serie di compilatori per ogni tipo di piattaforma. Noi useremo Visual C++. Ma in prima istanza impareremo come utilizzare il compilatore da linea di comando in modo da capire la corretta sequenza delle operazioni che spesso nei grossi tool di programmazione è trasparente all’utente. Nota: prima di iniziare dobbiamo settare le variabili di ambiente in modo tale da essere in grado di eseguire il nostro compilatore in qualunque posizione si trovi il nostro sorgente. - settare la variabile PATH con la dir C:\Programmi\Microsoft Visual Studio\VC98\Bin\ di Visual C++ Salviamo in un file “sorgente02.c” il nostro sorgente (codice 2) che abbiamo scritto in precedenza. Apriamo un prompt di MS-Dos e andiamo nella directory in cui è contenuto il file appena salvato. Eseguiamo il seguente comando in dos c:\>...\ cl /c sorgente02.c Dove cl.exe è il nostro compilatore visual c. Il comando appena eseguito ha generato il sorgente assembler. Il passaggio successivo è la fase di linking. Programmazione Grafica aa2006/2007

9 Programmazione Grafica aa2006/2007
Primo programma Step 3 :: Linking Dal nostro file sorgente02.obj ora dobbiamo linkarlo. Useremo sempre il nostro compilatiore ma questa volta con il flag “/l” e l’elenco delle librerie che ci servono. Eseguiamo il seguente comando in dos c:\>...\ cl sorgente02.c /l Dopo il comando viene generato il file sorgente02.exe Nel nostro caso nessuna libreria è stata usata quindi viene generato il sorgente senza nessun problema. Per eseguire il programma basta scrivere nel prompt di MS-Dos il nome del file. Ottenete come output nella vostra console: Corso di PG Con questi semplici passaggi abbiamo voluto far capire come deve essere la procedura di compilazione per un programma C. La cosa importante da ricordare è che qualunque applicazione voi usiate per compilare i vostri progetti essa eseguirà sempre queste procedure nella sequenza illustrata. Programmazione Grafica aa2006/2007

10 Programmazione Grafica aa2006/2007
Esempio Parte 01 :: Codice sorgente // Direttive per il preprocessore // #include <stdio.h> // Pre-processore #define COSTANTE_01 30 // Pre-processore #define COSTANTE_02 50 // Pre-processore // // Definizione dei tipi typedef int intVector[3]; // // dichiarazione funzioni void printValues (intVector vec); int sumVectorValues (intVector vec, int times); // Programmazione Grafica aa2006/2007

11 Programmazione Grafica aa2006/2007
Esempio Parte 02 :: typedef // Definizione dei tipi // typedef int intVector[3]; // La parola chiave typedef viene utilizzata per assegnare un alias ad un qualsiasi tipo fondamentale oppure derivato (introdotto dall'utente e derivato dai tipi fondamentali). Con typedef non si definisce un nuovo tipo, ma si introduce un nome che corrisponde a un tipo definito. La sintassi è la seguente: typedef nome_tipo nuovo_nome_tipo; Programmazione Grafica aa2006/2007

12 Programmazione Grafica aa2006/2007
Esempio Parte 03 :: Codice sorgente // implementazione funzioni // void printValues(intVector vec) { ... Implementazione ... } int sumVectorValues(intVector vec, int times) // Main function int main(int argc, char *argv[]) intVector myVector; // variabile di tipo intVector return 0; // valore di ritorno Programmazione Grafica aa2006/2007

13 Programmazione Grafica aa2006/2007
Esempio Parte 04 :: printValues // implementazione funzioni // void printValues(intVector vec) { // Funzione per la gestione dell'output su console printf("Vec :: [%d,%d,%d]",vec[0],vec[1],vec[2]); } La funzione riceve in ingresso come parametro una variabile di tipo intVector. L’unica cosa che succede all’interno della funzione è che i valori della funzione vengono stampati su standard output tramite la funzione printf. Programmazione Grafica aa2006/2007

14 Programmazione Grafica aa2006/2007
Esempio Parte 05 :: printf int printf ( const char * format [ , argument , ...] ); La funzione stampa una serie di argomenti secondo uno schema di formattazione. Format: Stringa che contiene del testo da essere stampato Ha il seguente prototipo: %[flags][width][.precision][modifiers]type argument(s): Parametri opzionali che contengono i valori/dati da essere visualizzati secondo la formattazione prescelta. Return Value: in caso di errore ritorna un numero negativo altrimenti ritorna il numero di caratteri stampati. Es: printf ("Some different radixes: %d %x %o %#x %#o \n", 100, 100, 100, 100, 100); printf ("floats: %4.2f %+.0e %E \n", , , ); Some different radixes: x floats: e E+000 Programmazione Grafica aa2006/2007

15 Programmazione Grafica aa2006/2007
Esempio Parte 06 :: sumVectorValues int sumVectorValues(intVector vec, int times) { int i; // local var for(i=0;i<times;i++) // ciclo for vec[0] += vec[0]; // a = a + a vec[1] += vec[1]; // a = a + a vec[2] += vec[2]; // a = a + a } printValues(vec); // richiamo la funzione printValues return vec[0]+vec[1]+vec[2]; // valore di ritorno La funzione prende in ingresso 2 valori, un intVector e un intero. Viene eseguito un ciclo per i numero di volte (times). Nel ciclo sommo il valore delle componenti del vettore x , y, z a se stesso. Una volta uscito dal ciclo chiamo la funzione printValues a cui passo il mio vettore per essere stampato. In ultima istanza passo come valore di ritorno la somma delle tre componenti del vettore risultante dalle operazioni precedenti. Programmazione Grafica aa2006/2007

16 Programmazione Grafica aa2006/2007
Esempio Parte 07 :: main // Main function int main(int argc, char *argv[]) { intVector myVector; // variabile di tipo intVector int res; // variabile int myVector[0] = 1; // primo elemento dell'array myVector[1] = 1; // secondo elemento dell'array myVector[2] = 1; // terzo elemento dell'array res = sumVectorValues (myVector, 4); // richiamo la funzione sumVectorValues printf("\nRes :: %d",res); // gestione dell'output su console return 0; // valore di ritorno } La funzione main, è la prima funzione invocata in esecuzione. Istanzia una variabile “myVector”di tipo intVector. La variabie myVector viene inizializzati ai valori 1,1,1. Eseguo la funzione “sumVectorValues” e il suo valori di ritorno lo salvo nell variabile res. Stampo il valore della variabile res. Programmazione Grafica aa2006/2007

17 Programmazione Grafica aa2006/2007
Funzioni Passaggio di parametri #include <stdio.h> void function (value) { value++; // value = 4 } void main (void) int value = 3; function (value); // value = 3 Il linguaggio C utilizza il passaggio dei parametri alle funzioni per valore. Per ottenere il passaggio per riferimento occorre utilizzare i puntatori. Programmazione Grafica aa2006/2007

18 Programmazione Grafica aa2006/2007
Struct Struct struct box { char name[36]; int numeroBiro; float profondita; }; struct box cassetto; Viene cosi definita una nuova struttura box e definita cassetto di tipo struct box. Una struttura puo' essere pre-inizializzata al momento della dichiarazione: struct box cassetto={“sofa", 5, 40.50}; Per accedere ai membri (o campi) di una struttura il C fornisce l'operatore ".". Ad esempio: cassetto.numeroBiro = 35; Programmazione Grafica aa2006/2007

19 Allineamento byte nelle struct
Occupazione di memoria di una struct: non è data dalla somma delle occupazioni dei singoli campi dipende dall’ordine in cui vengono definiti si deve prestare attenzione all’allineamento dei byte dei campi rispetto alla word (4 byte – 32 bit nel nostro caso). Esempio: struct con un intero e due char occupazione memoria del tipo char: 1 byte occupazione memoria del tipo int: 4 byte Sarebbe char + char + int = 6 byte ma…… …………cosa succede in questi due casi? typedef struct _mia_struct1 { char c1; int n; char c2; } mia_struct1; typedef struct _mia_struct2 { int n; char c1; char c2; } mia_struct2; Programmazione Grafica aa2006/2007

20 Allineamento byte nelle struct
Una word viene riempita con uno o più dati. Se un dato non può essere contenuto esattamente in una word si salta alla word successiva. typedef struct _mia_struct1 { char c1; int n; char c2; } mia_struct1; 4 8 12 c1 Offset n c2 Offset Occupazione totale : 12 byte (!) typedef struct _mia_struct2 { int n; char c1; char c2; } mia_struct2; 4 8 12 n c1 c2 Offset Occupazione totale : 8 byte (!) Programmazione Grafica aa2006/2007

21 Strutture di controllo
Condition Statement if (expression) statement1 else statement2 o expression1 ? statement1 : statement2 switch (expression) { case item1: statement1; break; case item2: statement2; break; case default: statement; break; } Cicli for (expression1; expression2; expression3) statement; while (expression) statement; Programmazione Grafica aa2006/2007

22 Programmazione Grafica aa2006/2007
sprintf sprintf int sprintf ( char * buffer, const char * format [ , argument , ...] ); La funzione scrive una serie di argomenti secondo uno schema di formattazione, in un buffer. Buffer: Buffer dove vengono scritti i valori Format: Stringa che contiene del testo da essere stampato Ha il seguente prototipo: %[flags][width][.precision][modifiers]type argument(s): Parametri opzionali che contengono i valori/dati da essere visualizzati secondo la formattazione prescelta. Return Value: in caso di errore ritorna un numero negativo altrimenti ritorna il numero di caratteri stampati. Programmazione Grafica aa2006/2007

23 Programmazione Grafica aa2006/2007
sprintf sprintf #include <stdio.h> int main (void) { char buffer [100]; int n, a=10, b=3; n = sprintf (buffer, "%d + %d è %d", a, b, a+b); printf ("[%s] is a %d chars string\n",buffer,n); return 0; } Output: [ è 13] is a 11 chars string Programmazione Grafica aa2006/2007

24 Programmazione Grafica aa2006/2007
Rand Rand int rand (void) La function "rand" consente di estrarre un numero pseudo-casuale. n=rand(); La sequenza di numeri ottenuta con la "rand" è però sempre la stessa, per avere una sequenza che sia imprevedibile è necessario fornire alla "rand" un seme di avvio diverso ogni volta che essa viene richiamata. Per tale scopo è necessario usare la "srand". Il parametro che deve essere passato alla "srand" è un "unsigned int". srand(437U); Ogni valore diverso del seme dà inizio ad una diversa sequenza di numeri. Affinchè la sequenza possa essere imprevedibile è necessario passare alla "srand" un valore imprevedibile per il seme. Un modo di fare ciò è quello di usare il clock di macchina. srand ((unsigned int) time((NULL)); La funzione "time(NULL)" ritorna l'ora corrente; la costante "NULL" è definita nello header "<stdio.h>". Il valore restituito da tale function viene convertito tramite un "cast" al tipo "unsigned int". Programmazione Grafica aa2006/2007

25 Programmazione Grafica aa2006/2007
File fopen FILE *stream; stream = fopen ("myfile.dat","rb"); if ((stream = fopen ("myfile.dat","rb"))==NULL) { printf("Can't open %s \n", "myfile.dat"); exit(1); } fclose(stream); FILE *fopen(char *name, char *mode) I files sono l'esempio piu' comune di stream. Per aprire un puntatore al file si utilizza la funzione fopen(). Tale funzione ritorna un puntatore a FILE. La stringa "name" e' il nome del file su disco a cui vogliamo accedere; la stringa "mode" definisce il tipo di accesso. Se per una qualsiasi ragione il file risulta non accessibile, viene ritornato un puntatore nullo. Le possibili modalita' di accesso ai files sono: * "r" (read), * "w" (write), * "a" (append). e: *”t” (modalità ASCII - default), *”b” (modalità binaria). Per aprire un file dobbiamo avere una stream (puntatore al file) che punta ad una struttura FILE. Ogni volta che apriamo un file dobbiamo SEMPRE chiuderlo. Programmazione Grafica aa2006/2007

26 Lettura e scrittura da file ASCII
fprintf - fscanf int fprintf(FILE *stream, char *format, args ...) int fscanf(FILE *stream, char *format, args ...) Le funzioni fprintf ed fscanf sono comunemente utilizzate per l'accesso ai files di testo. Sono simili a printf e scanf, tranne per il fatto che i dati sono letti dalla stream, che deve essere aperta con fopen(). Il puntatore alla stream viene incrementato automaticamente con tutte le funzioni di lettura/scrittura su file, quindi non e' necessario preoccuparsi di farlo manualmente. char *string[80]: FILE *stream, *fopen(); if ((stream=fopen(...)) != NULL) fscanf(stream,"%s",string); fclose(stream); char *string[80] FILE *fp; if ((fp=fopen("file.dat","r")) != NULL) fscanf(fp,"%s",string); fclose(fp); Programmazione Grafica aa2006/2007

27 Lettura e scrittura da file binari
I comandi fread e fwrite ci permettono di leggere/scrivere con una sola riga di codice una grande quantità di dati da file binari. int fread(void *buffer, int size, int num, FILE *fp); Il comando: legge dal file puntato da fp un numero num di dati di grandezza size byte e li mette nel buffer buffer ritorna il num di elementi letti int fwrite(void *buffer, int size, int num, FILE *fp); Il comando: scrive nel file puntato da fp un numero num di dati di grandezza size byte Pigliandoli dal buffer buffer ritorna il num di elementi scritti Programmazione Grafica aa2006/2007

28 Organizzazione del progetto
Divisione del codice Ci potrà essere molto utile ed anzi è caldamente consigliato organizzare su più file il progetto che si ha intenzione di affrontare. Le ragioni sono tante tra le più importanti ci sono sicuramente: - maggiore comprensione del codice un code reuse molto alto, spesso molte funzioni che scriviamo possono essere riutilizzate per altri scopi. Al nostro programma aggiungiamo ora altre 2 semplicissime funzioni; vediamo la dichiarazione delle funzioni: // dichiarazione funzioni // void printVector (intVector vec); void printInteger (int intVal); int sumVectorValues (intVector vec, int times); int sumIntValues (int intVal, int times); // Programmazione Grafica aa2006/2007

29 Organizzazione del progetto
Parte 02 Tutto il codice di “sorgente04” è contenuto in un unico file. Come possiamo vedere mano a mano che il codice cresce e si iniziano ad introdurre nuove funzioni la gestione del codice diviene più difficoltosa. L’ unica possibilità per rendere il tutto più chiaro è cercare di dividere il tutto su più files. Come primo approccio bisogna individuare le funzioni che fanno delle cose comuni, nel nostro caso abbiamo due funzioni che stampano su standard output, e altre due che gestiscono dati e li elaborano, ed infine abbiamo il main. Bene a questo punto dobbiamo cercare di avere non più 1 file solo ma almeno 3 file. Il primo deve contenere la main function. Il secondo set di files conterrà le funzioni di print. il terzo set di files conterrà le funzioni di gestione dei dati. Con “set di files” indico una coppia di file, header (*.h) e la sua implementazione (*.c). Vediamo nel nostro caso come risulteranno i files e come li compileremo. Programmazione Grafica aa2006/2007

30 Organizzazione del progetto
Parte 03 – sorgente05.c // Direttive per il preprocessore // #include <stdio.h> // Pre-processore #include "OperationsFunctions.h" #include "PrintFunctions.h" #define COSTANTE_ // Pre-processore #define COSTANTE_ // Pre-processore int main(int argc, char *argv[]) { //implementazione } La modifica evidente è la scomparsa delle funzioni e invece la comparsa di nuovi include i quali includono le dichiarazioni delle funzioni precedentemente implementate nel codice unico (sorgente04.c). Programmazione Grafica aa2006/2007

31 Organizzazione del progetto
Parte 04 – OperationsFunctions typedef int intVector[3]; int sumVectorValues (intVector vec, int times); int sumIntValues (int intVal, int times); OperationsFunctions.h #include "OperationsFunctions.h" int sumVectorValues(intVector vec, int times) { //implementazione } int sumIntValues (int intVal, int times) OperationsFunctions.c Programmazione Grafica aa2006/2007

32 Organizzazione del progetto
Parte 05 – PrintFunctions typedef int intVector[3]; int sumVectorValues (intVector vec, int times); int sumIntValues (int intVal, int times); PrintFunctions.h #include “PrintFunctions.h" int printValues(intVector vec, int times) { //implementazione } int printInteger (int intVal, int times) PrintFunctions.c Programmazione Grafica aa2006/2007

33 Organizzazione del progetto
Parte 06 - Compilazione Prima di tutto devo compilare i file OperationsFunctions.c e PrintFunctions.c. cl /c OperationsFunctions.c cl /c PrintFunctions.c cl /c sorgente05.c E genero i file obj dove sono contenute le dipendenze per le funzioni. Successivamente compilo il file sorgente05.c con le dipendenze di libreria (*.obj) generate prima. Adesso genero il sorgente con il seguente comando nel quale dovrò indicare le dipendenze dei 2 file esterni appena creati. cl Sorgente05.c /l OperationsFunctions.obj PrintFunctions.obj Il compilato è il medesimo della versione precedente. Programmazione Grafica aa2006/2007

34 Programmazione Grafica aa2006/2007
Puntatori Utilizzati per: Allocazione dinamica della memoria Passaggio di parametri per riferimento nelle funzioni Puntatori a funzione per gestione callback Una variabile dichiarata come puntatore ad un tipo conterrà l’indirizzo di una locazione di memoria int i, j, k; int *pi; i = 5; j = 10; k = 15; pi = &i; 5 i 0x12ff70 10 0x12ff74 j 15 0x12ff78 k 0x12ff70 0x12ff7C pi 0x12ff80 Programmazione Grafica aa2006/2007

35 Programmazione Grafica aa2006/2007
Puntatori Allocazione dinamica int *a = NULL; int dim = 6; a = (int*) malloc( dim * sizeof(int) ); for(i=0; i<dim; i++) a[i] = 1000 * ( i+1); free(a); 0x12ff74 0x431870 a 0x43186C 1000 a[0] 0x431874 2000 a[1] 0x431878 3000 a[2] 0x43187C 4000 a[3] 0x431880 5000 a[4] 0x431884 6000 a[5] Programmazione Grafica aa2006/2007

36 Programmazione Grafica aa2006/2007
Puntatori Allocazione dinamica - caso bidimensionale #define DIMX 8 #define DIMY 6 int i, j; int **m; m = (int **)malloc( DIMX * sizeof(int*) ); for(i=0; i<DIMX; i++) { m [i] = (int*) malloc( DIMY * sizeof(int) ); } m m[0] m[0][0] m[0][1] m[1] m[1][0] m[1][1] m[2] m[3] m[4] m[5] m[6] m[7] Programmazione Grafica aa2006/2007


Scaricare ppt "Introduzione al C Davide Gadia."

Presentazioni simili


Annunci Google