Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
vuoi
o PayPal
tutte le volte che vuoi
Il linguaggio C, diretto successore dell'assembly, è un linguaggio "di basso livello" perchè permette di svolgere operazioni di I/O molto basilari e con estrema semplicità, non a caso è molto usato per la scrittura di driver e kernel di sistemi operativi. E' un linguaggio di tipo procedurale, il che significa che usa una logica "a blocchi", detti comunemente funzioni. Questi blocchi di codice hanno un nome e sono delimitati da appositi simboli.
Il C è un linguaggio di tipo Case-Sensitive, quindi "ciao" sarà diverso da "CIAO" e diverso da "cIaO". Inoltre è un linguaggio Cross-Platform, cioè significa che può essere usato per programmare su qualsiasi S.O. Cercherò di essere il più generale possibile senza fare esempi riguardanti una piattaforma specifica. Per quanto mi riguarda lo preferisco a qualunque altro linguaggio di programmazione e spero sia lo stesso per voi. Iniziamo con alcuni concetti di base prima di addentrarci nella scrittura di codice vera e propria.
B. Ianero, Il C a 360°
Breve manuale di programmazione in C, pp. 65, pdf (0,9MB)
INTRODUZIONE
Ciao caro lettore, mi presento, mi chiamo Biagio Ianero e ti ringrazio di aver scelto questo libro per
imparare il Linguaggio C.
In questa guida verranno trattati tutti gli aspetti del linguaggio per una comprensione a 360°.
Ci saranno anche degli esempi pratici per capire meglio ciò che viene spiegato.
Elenco qui di seguito alcune convenzioni che userò nella scrittura:
Il codice sarà scritto con questo tipo di Font;
–
– Il codice delle applicazioni di esempio funzionanti verrà scritto “a colori” per una più facile
–
Per qualsiasi problema riguardante la comprensione della teoria, del codice od opinioni sul testo in
biagio.ianero@alice.it
generale contattami all'indirizzo:
Ti auguro una buona lettura ed una facile comprensione...
5
Biagio Ianero – Il C a 360°
IL LINGUAGGIO C
Il linguaggio C, diretto successore dell'assembly, è un linguaggio “di basso livello” perchè permette di
svolgere operazioni di I/O molto basilari e con estrema semplicità, non a caso è molto usato per la
scrittura di driver e kernel di sistemi operativi. E' un linguaggio di tipo procedurale, il che significa che
usa una logica “a blocchi”, detti comunemente funzioni. Questi blocchi di codice hanno un nome e sono
delimitati da appositi simboli che spiegheremo meglio nei capitoli successivi.
Il C è un linguaggio di tipo Case-Sensitive, quindi “ciao” sarà diverso da “CIAO” e diverso da “cIaO”.
Inoltre è un linguaggio Cross-Platform, cioè significa che può essere usato per programmare su qualsiasi
S.O.
Cercherò di essere il più generale possibile senza fare esempi riguardanti una piattaforma specifica.
Per quanto mi riguarda lo preferisco a qualunque altro linguaggio di programmazione e spero sia lo stesso
per voi.
Iniziamo con alcuni concetti di base prima di addentrarci nella scrittura di codice vera e propria.
LIBRERIE
Facciamo un esempio: vogliamo creare una macchina, ma da dove iniziamo?
Chi ci fornisce gli attrezzi? Dove prendiamo il motore? E le gomme?
Dovremmo fare tutto noi da zero, ma è per questo motivo che ci vengono in soccorso le librerie.
Nel nostro esempio la macchina è l'applicazione che vogliamo scrivere, ma per scriverla abbiamo bisogno
di funzioni basilari scritte già da altri programmatori da “includere” nel nostro codice, altrimenti se
dovessimo riscrivere ogni volta tutto da zero, il lavoro dell'app vero e proprio rappresenterebbe lo
0,00000001%.
FILE DI CODICE E COMPILAZIONE
Dove scriviamo il nostro codice C? La risposta è in un editor di testo più rudimentale possibile!
Questo codice sarà salvato con estensione .c al posto del classico .txt ed infine compilato.
La compilazione è un processo tramite il quale dal file.c ricaviamo il file eseguibile: la nostra
applicazione vera e propria.
Ci sono varie fasi per portare a termine questo processo che sono del tutto trasparenti al programmatore
grazie ai moderni compilatori che si trovano tranquillamente in rete.
La nostra applicazione sarà composta da più file.c, ognuno con un compito specifico, che saranno poi
uniti (sempre in fase di compilazione...) per formare un solo file eseguibile.
Un file.c può utilizzare una funzione scritta in un altro file.c, semplicemente importandolo.
Viene quindi da pensare ad una situazione di questo genere:
6
C'è però un problema: i file.c sono i file in cui viene scritto il codice vero e proprio, dove viene fatto il
cosiddetto “lavoro sporco”, sarebbe quindi molto difficile trovare una determinata funzione in un file
pieno di istruzioni di quel tipo.
Per rendere la cosa molto più semplice e pulita il C usa un'altro tipo di file, chiamato file di avente
header
estensione .h .
Quindi se esiste un file chiamato A.c, esisterà anche un file che avrà nome A.h, nel quale saranno solo
dichiarate tutte le funzioni implementate in A.c .
Tornando all'esempio della macchina, in un file chiamato Movimento.h troveremo le dichiarazioni delle
funzioni “sterza”, “accelera” e “frena”, mentre nel file Movimento.c troveremo tutte le istruzioni
necessarie per l'implementazione della sterzata, dell'accelerazione e della frenata della nostra automobile.
L'accoppiata file.c/file.h forma un di codice sorgente.
modulo
Come vediamo è il file header ad essere importato, il file grazie al quale riceviamo tutte le informazioni
sul file.c dello stesso modulo.
Vedremo più avanti la procedura corretta per l'importazione dei file header.
VARIABILI E TIPI DI DATI
Durante la scrittura del nostro codice avremo bisogno di trattare con tipi di dati diversi in base alle nostre
esigenze (numeri interi, decimali, ecc...).
Come sappiamo un bit può essere rappresentato da “0” o da “1” e mettendo insieme più bit si ottengono
rappresentazioni di numeri più grandi di 0 e di 1.
Più bit mettiamo insieme, più grande è il limite numerico che riusciamo a rappresentare.
Dove si raggruppano questi bit? E' qui che introduciamo il concetto di variabile.
In C qualsiasi tipo di dato è una variabile.
Essa non è nient'altro che un “agglomerato” di bit che ci rappresenta un determinato valore.
I tipi di dati primitivi che il C ci mette a disposizione sono i seguenti:
– variabile di tipo “int”, rappresenta un numero intero e, a seconda della macchina sulla quale si
compila il codice, può contenere 16 o 32 bit;
– variabile di tipo “float”, rappresenta un numero decimale ed è formata da 32 bit;
– variabile di tipo “double”, rappresenta un numero decimale ed è formata da 64 bit;
– variabile di tipo “char”, rappresenta un carattere e contiene 8 bit;
Capiamo quindi che una variabile può rappresentare al suo interno un totale di numeri pari a 2 (numeri
rappresentabili in un bit) elevato al numero di bit che la formano.
La variabile che contiene meno bit è il char poiché è formata da un solo byte (1 byte = 8 bit).
7
Biagio Ianero – Il C a 360°
I più attenti avranno già capito che il char, oltre che per rappresentare caratteri letterali, può essere anche
utilizzato come “piccolo int”; esso infatti potenzialmente può rappresentare 2^8 numeri, decisamente
inferiore alla variabile “int”, ma comunque utilizzabile.
Ovviamente queste variabili comprendono anche numeri negativi, ad esempio l'int va da -2147483648 a
+2147483648.
Se volessimo solo rappresentare numeri dopo lo zero, quindi raddoppiare il limite numerico positivo ed
azzerare il limite numerico negativo possiamo inserire la parola chiave “unsigned” prima di “int”.
A questo punto la variabile “unsigned int” potrà contenere numeri da 0 a 4294967296 (cioè 2147483648
* 2).
Ci sono inoltre parole chiave che possono “allungare” o “accorciare” il campo di bit contenuto nella
variabile: esse sono “long” e “short”.
Troviamo infine altre due parole chiave che sono “void” e “NULL”: la prima sta per “non-tipo” di dato, la
seconda per “nessun riferimento in memoria”.
Non si possono creare variabili di tipo void, ma questo tipo di dato viene usato per creare puntatori
generici e per non ritornare nessun valore da una funzione (esamineremo nello specifico questi due aspetti
più avanti). I nomi delle variabili non possono contenere spazi!
OPERATORI ARITMETICI
Il C mette a disposizione gli operatori aritmetici basilari per compiere operazioni matematiche.
Essi sono:
– “+” , simbolo che ci permette di eseguire l'addizione tra l'elemento a destra del simbolo e quello
alla sua sinistra;
– “-” , simbolo che ci permette di eseguire la sottrazione tra l'elemento a destra del simbolo e quello
alla sua sinistra;
– “*” , simbolo che ci permette di eseguire la moltiplicazione tra l'elemento a destra del simbolo e
quello alla sua sinistra;
– “/”, simbolo che ci permette di eseguire la divisione tra l'elemento a destra del simbolo e quello
alla sua sinistra;
– “%”, simbolo che ci permette di ottenere il resto di una divisione intera tra l'elemento a destra del
simbolo e quello alla sua sinistra;
Il simbolo “%” non esegue la percentuale!!!
Abbiamo poi anche altri operatori che io definisco “di comodo” perché servono semplicemente ad
incrementare (aumentare di 1) o decrementare (diminuire di 1) il valore di una variabile.
Ad esempio data la variabile “var” la scrittura:
var++ ++var
oppure
incrementano di 1 la variabile var, mentre:
var-- ––var
oppure
decrementano di 1 la variabile var. 8
Cosa cambia se ++ o -- si trovano prima o dopo del nome della variabile?
Cerchiamo di capirlo con un esempio:
Poniamo per semplicità che “var” valga 10.
Allora...
5 * var++
corrisponde a (5 * var) + 1 e il risultato sarà quindi 51.
Mentre...
5 * ++var
corrisponde a 5 * (var + 1) e il risultato sarà quindi 55.
OPERATORI DI CONFRONTO
Gli operatori di confronto sono un'altra categoria di operatori che possiamo usare per mettere a confronto
(chi l'avrebbe mai detto eh?) due elementi.
Semplicemente sono:
– “==”, operatore di uguaglianza (diverso da “=” !!!) che ritorna 1 (VERO) se le due variabili messe
a confronto sono uguali, altrimenti ritorna il valore 0 (FALSO);
– “!=”, operatore di disuguaglianza che ritorna 1 (VERO) se le due variabili messe a confronto
NON sono uguali, altrimenti ritorna il valore 0 (FALSO);
– “>”, ritorna 1 (VERO) se la variabile a sinistra è maggiore di quella di destra, altrimenti ritorna il
valore 0 (FALSO);
– “<”, ritorna 1 (VERO) se la variabile a sinistra è minore di quella di destra, altrimenti ritorna il
valore 0 (FALSO);
– “>=”, ritorna 1 (VERO) se la variabile a sinistra è maggiore o uguale a quella di destra, altrimenti
ritorna il valore 0 (FALSO);
– “<=”, ritorna 1 (VERO) se la variabile a sinistra è minore o uguale a quella di destra, altrimenti
ritorna il valore 0 (FALSO);
“=” non è la stessa cosa di “==”: il primo assegna il valore dell'elemento di destra
all'elemento a sinistra, il secondo invece effettua solo un confronto ma non modifica il valore degli
elementi.
OPERATORI LOGICI
Gli operatori logici più utilizzati in C sono “AND”, “OR” e “NOT”:
– “&&”, è l'AND e restituisce 1 (VERO) solo se entrambe le espressioni messe a confronto sono
vere, altrimenti 0 (FALSO);
– “||”, è l'OR e restituisce 1 (VERO) se almeno una delle espressioni messe a confronto è vera,
altrimenti 0 (FALSO);
– “!”, è il NOT ed inverte il valore di ritorno di un'espressione: se essa ritorna 1 (VERO), il risultato
sarà 0 (FALSO) e viceversa. 9
Biagio Ianero – Il C a 360°
Possiamo quindi riassumere in questo modo...
A B A AND B
0 0 0
0 1 0
1 0 0
1 1 1
A B A OR B
0 0 0
0 1 1
1 0 1
1 1 1
A NOT A
0 1
1 0
OPERATORI BIT A BIT
Altro tipo di operatori sono quelli che lavorano sui singoli bit.
Essi non sono molto usati nella programmazione in “User-Space”, ma comunque vengono elencati per
completezza.
Essi sono:
– “&”, and su bit, il risultato è 1 solo se entrambi i bit sono 1;
– “|”, or su bit, il risultato è 1 se almeno un bit vale 1;
– “^”, xor su bit, il risultato è 1 se solo uno dei due bit vale 1;
– “~”, not su bit, inverte ogni singolo bit;
– “>>”, shift a destra di bit, sposta a destra i bit di un dato elemento di “n” posizioni senza riporto;
– “<<”, shift a sinistra di bit, sposta a sinistra i bit di un dato elemento di “n” posizioni senza
riporto.
Per capire meglio la cosa facciamo un piccolo esempio...
Prediamo il numero 7 e il numero 9, che in binario sono rispettivamente “0111” e “1001”.
Usiamo tutti gli operatori bit a bit su questi due numeri secondo le regole elencate sopra.
0111 & 0111 | 0111 ^ ~ 0111 >> 0111 << 0111
1001 = 1001 = 1001 = ______ ______ ______
______ ______ ______
0001 1111 1110 1000 0011 1110
10
Come potrete notare gli ultimi tre operatori operano su un solo valore e non su una coppia di valori, come
invece fanno i primi tre.
FUNZIONI
Dove raggruppiamo tutte le istruzioni per il corretto funzionamento della nostra applicazione?
Sarebbe semplicemente folle scrivere tutte le istruzioni una dietro l'altra: non ci orienteremmo più tra
tutto il codice nel giro di venti minuti.