Il manuale
Learn C On The Mac si presenta come un
Complete Course in C Programming for the Beginner, e comincia proprio dalle basi per arrivare ad argomenti complessi come alberi di ricerca binari, puntatori a funzione, ricorsione, fino ad aprire le porte verso il mondo Objective-C nel dodicesimo capitolo che nella sostanza chiude il libro, e di cui riparleremo più avanti. C'è da dire che la scelta di programmare in C sotto Mac OS X, per di più usando XCode, può sembrare opinabile, una specie di controsenso, come prendere un lussuoso taxi per fare pochi metri di strada, anche se forse qualche motivo fondato possiamo anche trovarlo.
Il
primo capitolo presenta il libro, con un cenno al contenuto di ciascuno dei rimanenti capitoli, e il prerequisito richiesto per la sua lettura, ovvero saper usare Mac OS X; un cenno anche alle motivazioni per l'apprendimento del linguaggio C, visto soprattutto come base e punto di partenza su cui innestare in seguito l'apprendimento della programmazione orientata agli oggetti, in particolare Java e Objective-C.
Il
secondo capitolo sviluppa un argomento importante, ma non ancora legato alla programmazione vera e propria, ovvero
Go get the Tools: come procurarsi attraverso il sito
Apple Developer Connection gli strumenti di lavoro, in particolare XCode, dopo la registrazione, gratuita e obbligatoria, al sito citato. Dopo l'installazione, descritta passo passo con parecchi dettagli, si passa a spiegare il concetto di IDE e a mostrare il programma in funzione, con la creazione di un primo progetto per Mac OS X (
Command Line Utility), il suo primo salvataggio e l'esecuzione nella finestra di
Debug. In chiusura di capitolo, vengono fornite le indicazioni utili a scaricare il codice sorgente dal
sito del libro.
Il
terzo capitolo non ricomincia proprio dove terminava il secondo, ovvero all'interno di XCode, ma parte da alcune considerazioni sui motivi per scrivere un programma e sulla scelta del linguaggio di programmazione più adatto: giusto per fare un esempio rimanendo in casa Apple, l'automazione di Mac OS X riesce meglio con AppleScript (di cui in un box successivo viene dato un esempio), che però ha lo stesso svantaggio di VBA di Excel, ovvero non è molto utile al di fuori del suo ristretto ambito. La motivazione per scegliere C invece di Java oppure Objective-C sta(rebbe) invece nel fatto che questi ultimi si basano appunto sull'illustre antenato, una spiegazione convincente, ma fino a un certo punto: è vero che prima di correre si impara a camminare, ma troppa prudenza può allungare a dismisura il percorso.
Terminata la premessa con un paio di titoli Apress sulla programmazione Mac, Cocoa e iPhone, si riprende dai semplici progetti XCode con un programma che somma i numeri da uno a dieci, il cui sorgente viene esaminato per spiegare (anche visivamente) cos'è la compilazione, con dei cenni alle librerie, in particolare alla libreria standard, e con questi argomenti (sorgente, codice oggetto, eseguibile), il capitolo si chiude.
Il
quarto capitolo si occupa dei
mattoni con i quali si costruiscono i programmi C (e non solo), ovvero
le funzioni; per spiegare il concetto si passa dalla chiamata diretta della
printf alla scrittura di una funzione, la quale, a sua volta, ha il compito di effettuare la chiamata. Questa sottigliezza può sembrare concettualmente un po' contorta, ma serve a verificare in modo immediato nello standard output il corretto funzionamento dei programmi di esempio.
Abbiamo dunque l'anatomia della funzione (dichiarazione, corpo), un intermezzo sulla necessità di scrivere algoritmi concettualmente chiari e privi di errori, una divagazione sulla storia di C e sulla possibilità di usare il terminale per la programmazione in C, comprensiva di cenni su
man, un'altra sezione sul pannello
Group and Files della finestra XCode, e il capitolo si chiude con una seconda versione del programma
Hello, che usa la funzione definita dall'utente per la chiamata a
printf, osservando come il risultato sia lo stesso della prima versione, e come sia possibile chiamare ripetutamente la stessa funzione per ripetere l'output a volontà sulla console. Vengono poi generati alcuni errori di compilazione omettendo alcune parentesi o scrivendo in maiuscolo alcuni termini, per dimostrare che il linguaggio C è
case-sensitive. Il capitolo termina con alcuni semplici esercizi sugli argomenti trattati nell'ultima sezione, ovvero dedicati alla generazione di errori.
Il
quinto capitolo introduce due argomenti importanti:
variabili e
operatori. L'esposizione è chiara anche se non entusiasmante: si tratta di aspetti fondamentali, ma anche piuttosto noiosi, comunque l'introduzione delle variabili come contenitori, per quanto non originale, è abbastanza efficace; seguono le regole e le convenzioni per la denominazione, lo spazio occupato dai diversi tipi di dato, la notazione in complemento a due per i numeri con segno, e gli operatori, primo tra tutti quello per l'assegnamento di valori e poi quelli di incremento, in particolare
++,
+= ecc.
Vengono poi riassunti gli stessi argomenti grazie ai file di esempio, i soliti scaricabili dal sito del libro. Ancora una volta ritorna il
Terminale, questa volta per provare alcuni programmi con l'uso delle sequenze di
escape, e con il comando
which cc per sapere di quale compilatore si sta facendo uso. A questo punto vengono introdotti alcuni consigli sulle modalità di scrittura del codice (indentazione, commenti, dove mettere la parentesi graffe). Infine, gli esercizi che riguardano soprattutto gli operatori matematici.
Con il
sesto capitolo si muove ancora qualche passo nella programmazione C, e non è difficile capire che si passa al controllo del flusso, ovvero le
parole chiave che permettono di modificare l'ordine di esecuzione delle istruzioni. Si comincia con
if, con un semplice confronto relativo al valore di un intero (
se è maggiore di sei stampa...), e con un saggio consiglio: meglio anteporre il valore alla variabile per non incorrere nel classico errore di assegnare un valore invece di confrontarlo. Per questo,
if ( 0 == myInt ) è migliore di
if ( myInt == 0 ).
Viene poi data la definizione di
espressione (
anything that has a value), a parte
void di cui si parlerà più avanti, e di cui vengono esaminati i valori di verità, attraverso gli
operatori di valutazione e gli
operatori booleani con le relative tavole di verità. Tutti questi argomenti vengono poi presentati nel file di esempio relativo al capitolo, prima di procedere verso ulteriori argomenti, come i cicli
for, ma anche i blocchi di codice racchiusi tra parentesi graffe, il
semicolon o punto e virgola;
do,
switch e
break, anche loro con il relativo file di esempio da far girare con XCode.
Prima del
settimo capitolo, dedicato ai
puntatori, arrivano gli ormai abituali esercizi, non molti in verità, ma pur sempre utili per
prendere la mano con gli argomenti appena visti. I puntatori vengono paragonati, come indirizzi di memoria di una variabile, all'etichetta presente su un libro, la quale ne identifica la collocazione sullo scaffale in biblioteca, un paragone non perfetto, ma efficace almeno quanto quello dell'indirizzo di casa. Per quanto riguarda l'uso dei puntatori, vengono presentati gli operatori
address-of e lo (pseudo) operatore
star. Non manca anche qui una piccola divagazione sulla quantità di memoria indirizzabile a 16, 32 o 64 bit.
Siamo così giunti ai parametri funzione, ovvero la possibilità di condividere variabili tra funzione chiamante e funzione chiamata: se non esistesse questa possibilità, il valore in uscita dalla funzione andrebbe sempre perso. In questa parte viene anche introdotto il concetto di
ambito, che ho trovato talvolta impropriamente tradotto come
scopo, dall'inglese
scope. Infine, insieme ad altri argomenti — mi limito a quelli essenziali — viene precisata la differenze tra
parametro, ovvero il valore passato alla funzione, e
argomento, la variabile dichiarata allo scopo di ricevere quell'argomento; i due termini vengono a volte usati come sinonimi, ma è sempre bene aver chiara la differenza.
A questo punto vengono esaminati esempi di funzioni con passaggio dei parametri per valore o per riferimento, e le relative differenze tra quello che succede nei due casi. A pagina 138 c'è un box che ho trovato leggermente offensivo dove si spiega in due righe cosa vuol dire elevare un numero al quadrato, poi il discorso prosegue con gli esempi prima di concludersi con le
variabili globali e i
valori di ritorno delle funzioni, sottolineando qui di passaggio come
printf ritorni un intero, che rappresenta il numero di caratteri generati, e come sia buona norma evitare valori di ritorno non inizializzati. Da qui in poi ci sono gli esempi di codice, con una funzione per generare numeri primi, una per generare potenze di numeri e una sezione dedicata all'uso del
debugger.
L'
ottavo capitolo si apre sottolineando che ormai il livello raggiunto dall'aspirante programmatore C dovrebbe essere abbastanza alto, prima di introdurre questa parte piuttosto lunga dedicata ai tipi di dato, che comincia con un programma di esempio nel quale si usa l'operatore
sizeof per indagare lo spazio occupato da variabili
float,
double e
long double, e che anticipa l'argomento
typecast sviluppato meglio più avanti nel libro. Vengono presentati argomenti come gli specificatori di formato, gli arrotondamenti, le modalità di salvataggio dei numeri, gli intervalli dei diversi valori numerici, i criteri di scelta dei tipi di dato, che devono tener conto di precisione, prestazioni e sicurezza.
Analizzando il tipo di dati
char, viene approfondita in particolare, anche per motivi storici, l'analisi del set di caratteri ASCII, sia pure con un cenno anche a
Unicode. Il progetto di esempio esaminato mostra l'intercambiabilità fra caratteri e numeri interi, accennando anche ai rischi che si possono correre quando si usa un set di caratteri differente. Altri rischi di errore si possono evitare usando la libreria standard invece di far conto sul fatto che aggiungendo 32 a un carattere ASCII si ottiene la versione in maiuscolo dello stesso.
L'argomento che segue (e conclude, un po' più avanti il capitolo) è un approfondimento delle stringhe, con un progetto di programma
word count, non originalissimo, ma che può essere una guida efficace al completamento delle cose da sapere in materia, compreso l'uso dei puntatori e la relativa aritmetica.
Dopo i tipi di dati presenti nel linguaggio e gli array, con il
nono capitolo è il turno delle strutture dati costruite dal programmatore, che permettono di descrivere oggetti non omogenei come sono invece quelli che formano gli array. Come esempio per introdurre l'esigenza di personalizzare le strutture dati viene presentata una collezione di DVD, nella quale si deve tener traccia del titolo, del voto di apprezzamento, e di un commento. In prima battuta si potrebbe realizzare la gestione attraverso un array (magari a tre dimensioni), poi si può passare ad una struttura dati dove le informazioni vengono suddivise in tre campi di tipo
char, e passando una
struct come parametro alle funzioni che aggiornano i dati, e infine come
linked list, in modo da ottimizzare il consumo di risorse evitando di riservare spazio in memoria laddove questo può rimanere inutilizzato.
Nel corso del capitolo vengono dunque presentati diversi argomenti importanti — tra questi anche le istruzioni o direttive
#define,
malloc() e
free() — e di un certo rilievo pratico, che non manca anche all'applicazione di esempio; c'è invece una mancanza importante, ovvero la capacità di salvare i dati su disco per poterli recuperare in seguito. Di questo argomento, e dei file in generale, si occupa il
decimo capitolo: dopo una descrizione estremamente sintetica di file come flusso di byte consecutivi, e una infarinatura altrettanto breve sull'organizzazione dei file in UNIX, si parte subito con le funzioni di apertura, chiusura, e di conseguenza lettura e scrittura dei file.
Anche in questo capitolo abbiamo dei progetti di esempio, che permettono di accennare ad alcune caratteristiche di XCode, in particolare le modalità di aggiunta e rimozione di un file ad un progetto esistente, e l'organizzazione dei file nelle cartelle del progetto. Con il secondo progetto vengono usate le modalità di aggiornamento unite a quelle di lettura, scrittura e aggiunta ai file.
L'
undicesimo capitolo è intitolato
advanced topics e inizia complimentandosi con chi è arrivato a questo punto, per poi introdurre alcune tecniche utili a migliorare ancora. Si comincia con il
typecasting, ovvero la traduzione implicita o esplicita da un tipo di dato ad un altro; si prosegue con le
union, che consentono l'uso di uno solo dei diversi campi da cui sono formate (somiglianze e differenze con le
struct vengono opportunamente sottolineate). C'è poi una sezione dedicata alla
ricorsione, che continua nelle due successive dedicate agli
alberi binari e
puntatori a funzione.
Gli ultimi argomenti del capitolo sono gli
operatori booleani e le
operazioni di bit-shifting, ma anche l'operatore
? nelle
espressioni condizionali, la creazione di nuovi tipi con
typedef e di tipi enumerativi con
enum, le
variabili statiche, e si conclude con alcune funzioni di utilità per le stringhe, ovvero
strncpy(),
strncat(),
strncmp(),
strlen(), rimandando ad una pagina di documentazione per ulteriori approfondimenti.
Il
dodicesimo capitolo (
Where Do You Go from Here?) sottolinea come, una volta giunti alla fine del percorso, ci si trova a conoscere due aspetti importanti della programmazione per Mac OS X, ma senza saperli ancora unire. Infatti i programmi vivono sostanzialmente sulla finestra debug di XCode, e non è stata prodotta una sola finestra, o qualsiasi altro elemento della ricca interfaccia grafica che caratterizza Mac OS X. A questa situazione si rimedia parzialmente grazie alla creazione passo passo di un progetto visuale, che consiste purtroppo soltanto di una finestra vuota, ma vuole essere un'apertura verso il mondo delle interfacce grafiche a cui approdare, magari con la guida di un altro manuale Apress.