giovedì 15 novembre 2018

C e C++: Appunti di una riscoperta 4

Ora che sappiamo dei token, vediamo con quali di questi possiamo scrivere il programma C più piccolo che ci sia e analizzare il programma C scritto per Hello World.

Iniziamo con il programma più piccolo.

main(){}

Questo è tutto. Abbiamo un programma avente la bellezza di 5 token.

  • Il primo è main, identificativo della funzione. Una funzione speciale che deve obbligatoriamente chiamarsi main e a cui è affidato il controllo appena il programma è avviato. 
  • Abbiamo due parentesi tonde, che chiariscono che main è una funzione e al cui interno trovano posto gli argomenti o parametri formali. I parametri formali sono delle informazioni passate alla funzione per ulteriori elaborazioni o per modificarne il comportamento. In questo caso la funzione non fa uso di parametri e quindi non c'è nulla. 
  • Abbiamo due parentesi graffe, utilizzate per racchiudere i blocchi di codice. In particolare qui non c'è nessuna istruzione. 
Possiamo quindi dire che questo programma avviato terminerà dopo non aver fatto nulla dato che nulla c'è nel suo blocco d'istruzioni racchiuso dai token { e }.

Diciamo che tutto questo è interessante ma non entusiasmante. E' interessante perché abbiamo capito che, perché ci sia un programma, deve esserci una funzione chiamata main che sarà eseguita per prima. Il fatto che si dica che sia la prima significa anche che non sarà l'unica, infatti vedremo che è possibile definire tutte le funzioni desiderate organizzandole non necessariamente in un unico file.

Passiamo quindi al nostro Hello World:

#include "stdio.h"
main(){printf("Hello World");}


Notato nulla? Niente allarmismi, abbiamo solo eliminato degli spazi vuoti (gli accapo e gli spazi) che il compilatore avrebbe comunque ignorato riducendo tutto il programma in due righe. Però mettere qualche spazio migliora la leggibilità del codice.


#include "stdio.h"
 

main(){
    printf("Hello World");
}

Se main() sappiamo essere l'identificativo di una funzione, logica suggerisce che printf() all'interno del blocco d'istruzioni racchiuso tra i token { e } sia anch'essa una funziona, ma in azione. E' infatti utilizzata da main per produrre sulla console il letterale stringa passato come argomento (parametro attuale). I letterali stringa sono quindi sequenze di caratteri, numeri e simboli racchiusi tra ".

Ma dove è definita la funzione printf? Essa si trova tra le librerie standard del C. In particolare nella libreria STnDard dedicante all'Input/Output ossia la stdio. Abbiamo infatti nel nostro sorgente la prima riga, la #include, che non è una istruzione C ma un comando al compilatore, o meglio al preprocessore del compilatore, con il quale si chiede di incorporare nel nostro sorgente il file stdio.h. I file .h sono dei file d'intestazione o header al cui interno sono presenti prototipi di funzioni, e altro, e che fanno riferimento ad un file con lo stesso nome ma .c in cui tali funzioni sono definite. Quindi il preprocessore del C, letta la direttiva #include, incorporerà le intestazione o prototipi delle funzioni presenti nel file header. Il compilatore provvederà a unire il nostro sorgente con quello che definisce le funzioni prototipate andando a generare l'eseguibile. In questo modo printf sarà definita e il programma sarà eseguito senza errori, sfruttando una funzione presente nelle librerie di funzioni dedicatet all'I/O. La direttiva al compilatore deve essere terminata con un accapo.

Il punto e virgole indica la fine di una istruzione C e deve essere posto al termine di ogni istruzione.

Quindi ora sappiamo che
  • la main è la funzione chiamata in fase di avvio del programma, 
  • le istruzioni del main (ma di qualunque definizione di funzione) sono racchiuse in un blocco istruzioni e che i blocchi istruzioni iniziano con il token { e finiscono con il token }
  • che i parametri formali delle funzioni sono racchiusi tra i token ( e ) e che se assenti significa che la funzione non richiede parametri attuali per funzionare come nel caso del main
  • che i parametri attuali delle funzioni, ossia quei valori che sono effettivamente passati alla funzione quando invocata (come per la printf in HelloWorld), sono anch'essi racchiusi tra i token ( e ).
  • che ogni istruzione C termina con il punto e virgola
  • che possiamo accedere a funzioni pronte all'uso definite in librerie (raccolte di definizioni di vari elementi tra cui le funzioni) semplicemente includendo i loro prototipi tramite un comando #include al preprocessore e specificando il file header corrispondente
  • che le direttive al preprocessore devono essere terminate con un accapo
  • che i letterali stringa sono sequenza di caratteri, numeri e simboli racchiusi tra doppi apici
  • che la printf() è una funzione che accetta un letterale stringa e lo visualizza sulla console