C & C++ Generalità sul linguaggio C Dennis Ritchie Brian W. Kernighan Il C è un linguaggio di programmazione procedurale di alto livello. Progettato e realizzato da Dennis Ritchie e da Brian W. Kernighan nel 1972, fu sviluppato presso gli AT&T Bell Laboratories con lo scopo di ottenere un linguaggio di alto livello per l’implementazione dei sistemi operativi. Il linguaggio C nasce come evoluzione di altri linguaggi. Il linguaggio C nasce come evoluzione del linguaggio BCPL (Basic Combined Programming Language) e del suo successore, il linguaggio B. Benché strettamente legato a quest’ultimo sistema, il C può essere utilizzato con i principali sistemi operativi oggi disponibili. Dalla metà degli anni Ottanta, l’ANSI C divenne la versione ufficiale del linguaggio. Il C è un linguaggio compilato. Nella metà degli anni Ottanta il comitato X3JI1 dell’ANSI (American National Standards Institute) sviluppò uno standard per il linguaggio C che aggiungeva importanti caratteristiche e ufficializzava molte caratteristiche presenti nei diversi compilatori realizzati successivamente alla pubblicazione di K&R. Le principali caratteristiche del linguaggio C È un linguaggio general purpouse, ossia può essere impiegato per codificare progetti software di natura diversa, da quelli real time a quelli che operano su basi di dati, da quelli tecnico-scientifici sino alla realizzazione di moduli per il sistema operativo. È un linguaggio strutturato di tipo imperativo (o procedurale). I linguaggi C e C++ non sono linguaggi strutturati a blocchi poiché non consentono la dichiarazione di procedure e funzioni all’interno di altre procedure e funzioni. Nella versione ANSI, è facilmente portabile e perciò multipiattaforma; può infatti essere compilato su un’ampia gamma di computer. Il C riunisce in sé i migliori elementi dei linguaggi ad alto livello con la possibilità di controllo e la flessibilità del linguaggio Assembler. Le principali caratteristiche del linguaggio C Produce programmi efficienti. Essendo nato per implementare sistemi operativi, il C evita anche, ove possibile, qualsiasi operazione che possa determinare un decadimento del livello di efficienza del programma eseguibile. Produce programmi di dimensioni ridotte. Ha infatti una sintassi che si presta alla concisione e alla scrittura di codice compatto. Consente l’implementazione dei puntatori (fa ampio uso di puntatori per memoria, vettori, strutture e funzioni). Alcune delle lacune del C riguardano invece: Spesso non è facile trovare gli errori quando si programma in C. Un metodo scadente per l’identificazione di errori (che generalmente ne esclude l’utilizzo ai principianti). La facilità con cui si possono “violare le regole” del C. Il linguaggio C++ Bjarne Stroustrup Inizialmente il linguaggio C++ venne chiamato C con classi. Intorno alla prima metà degli anni Ottanta fu sviluppata un’estensione del linguaggio C chiamata inizialmente “C con classi” e , solo dopo qualche anno, ribattezzata C++. Il C++ mantiene il C come linguaggio base per non perdere gli indiscutibili vantaggi offerti da quest’ultimo. Il linguaggio C++ Il linguaggio C++ è un linguaggio autonomo indipendente dal C. Il C++ rappresenta un linguaggio autonomo indipendente dal C, venendosi a posizionare tra i linguaggi di medio livello. In particolare, l’introduzione di costrutti quali i template e le classi rende C++ un linguaggio multiparadigma (con particolare predilezione per il paradigma a oggetti e la programmazione generica). Il C e il C++ sono linguaggi per programmatori. Ciò che ha sempre differenziato il linguaggio C++ dagli altri linguaggi artificiali è il fatto di non essere stato sviluppato da gruppi di ricerca appositamente predisposti per creare un nuovo linguaggio di programmazione, ma creato dai programmatori con l’obbiettivo di rendere più semplice l’attività di codifica di programmi notevolmente lunghi e complessi. Descrizione sintattica dei linguaggi di programmazione Un linguaggio di programmazione non è un linguaggio naturale. Lo studio di un linguaggio di programmazione, proprio come lo studio di un linguaggio naturale (italiano, inglese, ecc.) si basa sul rispetto e sull’applicazione di precise regole grammaticali. I linguaggi di programmazione fanno parte dei cosiddetti linguaggi formali, cioè a quell’insieme di regole che definisce la struttura di frasi formalmente corrette. Formalismo utilizzato per descrivere la sintassi del linguaggio Le parole chiave del linguaggio saranno scritte in grassetto. Le parole scritte racchiuse tra le parentesi angolari < > rappresentano le categorie sintattiche, ossia elementi generali del linguaggio che, nei vari programmi, saranno sostituiti con opportune occorrenze. Ad esempio: A=B A=C+2*D <NomeVariabile> = <Espressione> C=0 I blocchi racchiusi tra parentesi quadre [ ] indicano l’opzionalità, ossia tali blocchi possono anche non essere presenti. Ad esempio: int <NomeVariabile> [= <ValoreIniziale>] I blocchi racchiusi tra parentesi graffe { } indicano la possibilità di ripetizione. Ad esempio: int <NomeVariabile> {,<NomeVariabile>} indica che subito dopo il nome della variabile è possibile inserire altri nomi separati da una virgola. Il simbolo | ha il significato di OR. Ciò significa che all’interno di una lista di parole chiave separate da questo simbolo occorre sceglierne soltanto una. Ad esempio: int | float <NomeVariabile> Gli elementi di un programma C++ Struttura di un programma C++ Facoltativo Direttive al processore Facoltativo Dichiarazione di variabili globali e/o dei prototipi delle funzioni OBBLIGATORIO Programma principale (funzione main) Facoltativo Funzione 1 Facoltativo Funzione 2 Facoltativo Funzione N Il programma principale (funzione main) La funzione main è la funzione principale di un programma codificato in C++ e come tale deve essere sempre presente. [<TipoRestituito>] main ([<ElencoParametri>]) { <Istruzione1>; <Istruzione2>; ……… <IstruzioneN>; } Il programma principale (funzione main) Il gruppo di istruzioni racchiuse all’interno della coppia di parentesi graffe { } definisce il corpo del programma. Il più semplice programma in C++ che si può scrivere è il seguente: main ( ) { } Il programma principale (funzione main) L’istruzione return fa in modo che la funzione restituisca il valore (o l’espressione) indicato. int main ( ) { return 0; } Con l’istruzione return la funzione restituisce il valore (o l’espressione) indicato. Naturalmente tale valore deve essere dello stesso tipo della funzione. Il programma principale (funzione main) Nel caso in cui non si voglia usare l’istruzione return occorre dichiarare esplicitamente che la funzione non restituisce alcun risultato. Per far questo occorre far precedere il nome main dalla parola chiave void: void main ( ) { } Il programma principale (funzione main) #include <iostream.h> È buona regola indentare le istruzioni al fine di garantire la leggibilità del programma. int main ( ) { cout << “Ciao mondo!”; return 0; } Un programma non indentato diventa difficile da leggere e da correggere. L’indentazione aiuta a seguire il flusso del controllo e, di conseguenza, a seguire la logica del programma. Sempre riferendoci all’istruzione return, si può notare che ogni istruzione in C++ termina con un punto e virgola (;). Su una singola riga è possibile scrivere più istruzioni, ma è buona norma scriverne solo una al fine di migliorare la leggibilità del codice. La preelaborazione del codice sorgente: le direttive al processore Programma sorgente e programma oggetto. Il linguaggio C++ è un linguaggio compilato. Come sappiamo, i compilatori sono programmi che accettano in ingresso un programma scritto in linguaggio di alto livello (detto programma sorgente) e lo traducono interamente in un programma in linguaggio macchina (detto programma oggetto): a traduzione ultimata, il programma potrà essere eseguito. A differenza di altri linguaggi, la compilazione in C++ prevede una prima fase di preelaborazione, detta precompilazione, svolta da un apposito modulo denominato preprocessore. La preelaborazione del codice sorgente: le direttive al processore Programma sorgente e programma oggetto. Le dichiarative di precompilazione sono istruzioni di dichiarazione per il processore. Le istruzioni di dichiarazione per il preprocessore vengono chiamate dichiarative di precompilazione o direttive al preprocessore e iniziano con il carattere # seguito dalla parola chiave include o define e dalla dichiarazione della direttiva. La direttiva #include consente di inserire nel file sorgente la libreria standard indicata dopo la diirettiva stessa. La preelaborazione del codice sorgente: le direttive al processore Programma sorgente e programma oggetto. Le dichiarative di precompilazione sono istruzioni di dichiarazione per il processore. Una libreria è un insieme organizzato di programmi utilizzati frequentemente nelle applicazioni e memorizzati su un dispositivo di memoria di massa. La direttiva va racchiusa all’interno di parentesi angolari o di doppi apici. Ad esempio, le direttive: #include <iostream.h> #include ‘‘iostream.h’’ indicano al compilatore di includere e compilare insieme al programma il file iostream.h che contiene i prototipi delle funzioni standard di input/output (I/O) del C++, richiamabili poi da un qualsiasi punto del programma. La preelaborazione del codice sorgente: le direttive al processore Programma sorgente e programma oggetto. Le dichiarative di precompilazione sono istruzioni di dichiarazione per il processore. #include <iostream.h> #include ‘‘iostream.h’’ L’estensione .h del file sta a indicare che i file in questione sono file di intestazione o file di header. Le dichiarazioni di inclusione #include non terminano con il punto e virgola. Le funzioni per la gestione dell’input/output La funzione cout ci consente di scrivere sul monitor. cout è abbreviazione di console output. Il simbolo << è detto operatore di output. La sintassi è la seguente: cout << <Espressione> | <Stringa> {<< <Espressione> | <Stringa>}; Ad esempio, l’istruzione: cout << “Ciao a tutti”; visualizza sul monitor la stringa Ciao a tutti. Ad esempio, l’istruzione: cout << 2+3+7; visualizza sul monitor il valore 12. Le funzioni per la gestione dell’input/output La funzione cin ci consente di leggere i dati provenienti dalla tastiera. cin è abbreviazione di console input. Il simbolo >> è detto operatore di input. La sintassi è la seguente: cin >> <NomeVariabile> {>> <NomeVariabile>}; Ad esempio, l’istruzione: cin >> Numero; consente di accogliere all’interno della variabile Numero il valore digitato dalla tastiera. Realizziamo il nostro primo programma in C++ #include <iostream.h> int main ( ) { cout << “Ciao mondo!”; return 0; } Dal codice sorgente al codice eseguibile I passi da eseguire per creare un file eseguibile sono i seguenti: 1. Scrittura del programma sorgente e memorizzazione dello stesso all’interno di un file con l’estensione .c, .cpp, .cp. 2. Compilazione del programma sorgente e ottenimento del programma oggetto memorizzato in un file caratterizzato dall’estensione .obj. Il compilatore, durante la fase di traduzione del codice sorgente in codice oggetto, verifica la correttezza formale del codice sorgente e segnala la presenza di errori che impediscono la creazione del file oggetto (con un messaggio error), oppure invia un warning quando rivela errori che consentono comunque di creare il file oggetto; i warning sono avvertimenti di situazioni anomale che potrebbero creare problemi in fase di esecuzione. 3. Linking del programma oggetto con le librerie standard del linguaggio dichiarate nel codice sorgente a opera di un particolare programma chiamato linker. Il risultato sarà il programma eseguibile memorizzato in un file caratterizzato dall’estensione .exe.