![]() |
| Dennis Ritchie |
![]() |
| Ken Thomson |
Dennis Ritchie è colui al quale viene attribuito la scrittura
del linguaggio c, scrittura effettuata su un sistema DEC PDP-11 (Digital Equipment Corporation Programmed Data Processor
model 11") con architettura a 16 byte, qui Dennis Ritchie fece girare il
primo programma scritto in linguaggio c; Il linguaggio c deriva da un processo
di sviluppo del linguaggio BCPL di Martin Richards che influenzò la scrittura
del linguaggio B di Ken Thomson. Agli arbori degli anni 70 e da
quest’ultimo linguaggio infatti che il linguaggio C viene ispirato ed
influenzato nella sua stesura, inoltre c’è da ricordare che il linguaggio c++
si basa su questo linguaggio e l’origine del linguaggio java e dato dalla
sintassi di quest’ultimo, possiamo quindi dire che java e figlio del linguaggio
c e c++. Il C è un linguaggio di tipo procedurale e riesce ad integrare
caratteristiche dei linguaggi di basso livello, come il linguaggio macchina e l'assembly, questo è il motivo per cui si usa anche l'espressione di medio
livello.
Il C e un linguaggio strutturato a blocchi anche se si distingue dal fatto
che a differenza di altri linguaggi più moderni che rientrano a pieno titolo in
questa categoria in c non e consentito richiamare le procedure o funzioni
internamente da altre di esse, questo pone il linguaggio c in una posizione
intermedia facendo si che esso non rientri poi tra i linguaggi con struttura a
blocchi.
Il linguaggio C blasonato per la sua potenza si è imposto come
linguaggio di riferimento per la realizzazione di software di sistema su gran
parte delle piattaforme hardware moderne. La standardizzazione del linguaggio
da parte prima dell' ANSI e in seguito dell' ISO garantisce la portabilità dei
programmi scritti in C standard, spesso detto ANSI C su
qualsiasi piattaforma. Oltre che per il software di sistema, il C è stato sin
da subito e ancora oggi un linguaggio dominante in molti applicativi
caratterizzati da una forte efficienza. Esempi tipici sono il controllo dei
processi industriali, le telecomunicazioni e il software real-time. Oggi, il
predominio del C in questi contesti è in parte diminuito a seguito dell'avvento
di nuovi linguaggi, come ad esempio il C++ che comunque un derivato c ma con
estensione ad oggetti. Anche se la sua complessità di apprensione oggi lo rende
meno attraente rispetto ad altri linguaggi di programmazione, per le forti
relazioni di implementazione dello sviluppo del funzionamento dell'hardware dei
computer il C ha, e continua ad avere, anche una notevole importanza didattica,
infatti non è un linguaggio particolarmente intuitivo per i principianti e in
particolare, a quelli sprovvisti di un adeguato background riguardante
l'elettronica dei calcolatori. Un tempo le scuole superiori e i corsi
universitari adottavano il linguaggio C per la formazione dello studente, come
linguaggio di riferimento, causa la sua importanza tecnica, oggi i percorsi
formativi trovano un'ulteriore motivazione nella crescente importanza di
linguaggi che derivano dal C, per esempio C++, Java, e C#, per mettere in condizione
lo studente di fare un approccio iniziale più rapido e intuitivo verso lo
sviluppo del software.
INTRODUZIONE
Questa pagina del blog è dedicata al linguaggio c e a
tutti i programmatori c qualsiasi sii il loro livello di esperienza che hanno
per questo linguaggio, infatti, aspira a offrire una risorsa in più di
materiale attendibile e affidabile su questo linguaggio e in fine per coloro
che nutriti d’interesse e che iniziano ad avvicinarsi al linguaggio c,
cercheremo di dare risposte a molte domande, mentre per chi sta iniziando da
poco l’apprendimento di questo linguaggio anche se e consigliabile avere un
minimo di esperienza per esempio nel riuscire a creare un piccolo programma e
quindi essere più agevolati a capire le pubblicazioni, purtroppo però il tempo
a disposizione da dedicarci a questo argomento
scarseggia a causa dei ritmi di vita createsi in questi anni a causa della
globalizzazione e della crisi economica, cercheremo di fare il meglio possibile
ma non ci sentiamo di indicare date precise sulle uscite al momento, grazie.
Limitazione struttura del linguaggio
C rispetto ad altri linguaggi.
Possiamo ottenere una struttura nel linguaggio c aggirando i vincoli e le sue limitazioni operando con le subroutine che si appoggiano a variabili locali in modo che non provocano blocchi in altre parti del codice nel corso della sua esecuzione, questo rende ovvia una certa portabilità del codice in altri programmi in modo più semplificato, sviluppare una funzione isolata fa si che ci si troverà la sua utilità nelle operazioni che essa svolge e non nel modo in cui tali operazioni sono svolte, occorre tener presente che nel linguaggio c è sconsigliato fare un uso eccessivo di variabili note in uno stesso programma rendendolo instabile e soggetto a bug questa e una delle limitazioni di questo linguaggio.
Possiamo ottenere una struttura nel linguaggio c aggirando i vincoli e le sue limitazioni operando con le subroutine che si appoggiano a variabili locali in modo che non provocano blocchi in altre parti del codice nel corso della sua esecuzione, questo rende ovvia una certa portabilità del codice in altri programmi in modo più semplificato, sviluppare una funzione isolata fa si che ci si troverà la sua utilità nelle operazioni che essa svolge e non nel modo in cui tali operazioni sono svolte, occorre tener presente che nel linguaggio c è sconsigliato fare un uso eccessivo di variabili note in uno stesso programma rendendolo instabile e soggetto a bug questa e una delle limitazioni di questo linguaggio.
Errori di sintassi e interpretazione.
Capita
molto spesso di riscontrare errori in fase di sviluppo che apparentemente
sembrano senza senso e incomprensibili, quindi e buona norma quando ciò accade
esaminare il codice per riscontrare le anomalie che generano l’errore in fase
di compilazione focalizzandoci sulla sintassi, partendo a ritroso dal punto
della segnalazione dell’errore, basta una piccola distrazione o una
dimenticanza per andare in contro il blocco del codice come per esempio
nel inizializzare un prototipo di funzione di un tipo per poi richiamarla dopo
decine, centinaia di righe di codice con un altro tipo di assegnazione per far
sì che il compilatore generi il blocco, un valido aiuto oggi c’è dato dalle ide
ma comunque il compilatore interpreterà una dimenticanza del genere come la
creazione di una nuova funzione, quindi nulla aiuta più di una buona formazione
personale specie quando il codice e molto esteso e diventa facile perdersi in
esso, molto importante in fine e tenere conto di un’accurata attenzione nella
punteggiatura del codice e non solo nel evitare sbagliate attribuzioni di tipo
di dati, ove non vi fosse stata creata una funzione intermedia di conversione
oppure in semplici assegnazioni di tipi di dato.
Indicizzazioni errate degli array.
E molto facile in fase di sviluppo fare errori negli array,
bisogna ricordare che l’indicizzazione parte da zero quindi un ciclo for del tipo: for (i = 1; i < 10
++i) prova[i] = i; ci restituisce un indice di nove elementi perché l'istanza avviene in questo modo int i, prova[10];
quindi la formula giusta è: for(i = 0; i < 10
++i) prova[i] = i;
Il prototipo di funzione.
Evitare il superamento dei
limiti dichiarati.
Quando si
sviluppa un programma in linguaggio c, bisogna tenere bene a mente i limiti in
base ai valori dei tipi di dati che dichiariamo nelle variabili o degli array
perché il codice è compilato normalmente e durante il debugging non è rilevato
alcun errore, questo potrebbe indurre il programmatore a un’errata analisi di
valutazione e individuazione degli errori durante i test del programma
riscontrando anomalie inattese.Il prototipo di funzione.
Il
prototipo di funzione e alla base della programmazione, infatti, e un errore
grave dimenticare tale passaggio, di seguito è illustrato un esempio di un
programma in virgola mobile con tipo di dati double dal costo di otto byte
della funzione prova che elabora il prodotto di due numeri
restituendoci il risultato.
/*
#include <stdio.h>
double prova(float c, float a);
int main(void)
{
float x, y;
printf("\n\n
inserisci un numero seguito dal punto e premi invio! \n\n ");
scanf("%f", &x);
printf("\n inserisci il secondo numero e premi nuovamente invio! \n\n ");
scanf("%f",
&y);
printf("\n
ECCO IL RISULTATO IN VIRGOLA MOBILE! \n\n %f", prova(x, y));
return
0;
}
double prova(float c, float a)
{
return c*a;
}
*/
Se avessimo dimenticato di inserire prima del
main() double prova (float c, float
a) avremmo ricevuto un errore perché main () attenderebbe un valore intero
a quattro byte mentre prova
restituirebbe un valore a otto byte.
Evitare gli errori negli
argomenti.
Ovvio e che i prototipi di funzione riescono a
catturare gran parte delle differenze fra i parametri e gli argomenti ma e
necessario fare attenzione in fase di sviluppo che il tipo di valori, passati a
una funzione sia corrispondente al tipo di argomenti attesi come risposta,
quando la funzione e in esecuzione, questo lavoro si rende indispensabile
specie se pensiamo a una funzione con più valori come argomenti il compilatore,
non riuscirà facilmente a distinguere l’attribuzione, quindi resta al
programmatore scrivere del buon codice per evitare errori, avendo una buona
base di formazione si può emarginare tale pericolo, facciamo ora un esempio con
la funzione scanf () che si aspetta
di ricevere l’indirizzo con questa sintassi (&) e non il valore degli argomenti.
int
a;
scanf("d", &a); GIUSTO
scanf("d", a);
SBAGLIATO
Anche se molti compilatori farebbero passare scanf (“%d”, a) l’errore si
manifesterà poi in fase di esecuzione.
Oltre i limiti dello stack.
Lo stack e alla base del compilatore, al suo
interno sono memorizzate le variabili locali sia per i parametri passati sia
per i valori restituiti dalle funzioni, ma bisogna sapere che la dimensione
dello stack ha un limite, quindi il superamento di questo limite porta il
programma a bloccarsi oppure alla sua errata esecuzione rendendo inefficaci le
operazioni di debugging, diventa facile trovarsi in situazioni dove si superano
i limiti dello stack di allocazione
per un uso eccessivo di funzioni ricorsive nidificate che generano un blocco
apparentemente inspiegabile del programma, e bene sapere che alcuni compilatori
c permettono di aumentare le dimensioni dello stack.
Utilizzo del debugger.
Oggi e quasi impossibile trovare un
compilatore che non ha integrato un debugger, è un programma di
individuazione degli errori e la loro eliminazione, l’aiuto che ci da il debugger e quello di eseguire il codice
costantemente nella fase di sviluppo ispezionando tutto il codice, analizzando
le variabili e impostare il breakpoint.
Importantissimo e per un programmatore
familiarizzare con questo strumento per scrivere del buon codice infatti la
fase di testing all'interno delle
software-house ha assunto negli anni un ruolo sempre più fondamentale e
indispensabile.
Teoria del debugging.
Di
primaria importanza nella programmazione viene rivestito il ruolo del
debugging, abbiamo vari metodi che vengono utilizzati dai programmatori ma il
metodo più appropriato e sicuramente quello incrementale anche se può sembrare
un rallentamento in fase di sviluppo.
Il metodo
del test incrementale ci permette di avere del sorgente funzionale sin dalle
prime fasi della scrittura per ogni pezzo di codice, ciò viene definita in
termini accademici unità operativa perché sempre funzionale per accentuare
ancora meglio questo processo dobbiamo immaginare il codice diviso in sezioni.
Applicando
la procedura incrementale di debugging non faremo altro che per ogni nuova
sezione di codice aggiunta a quello precedente già testato l’individuazione di
eventuali bug sul nascere e quindi di
poter intervenire in modo molto chiaro, tempestivo e in aree ben definite,
questo e ovvio che rallenta la fase iniziale di sviluppo del software ma
renderà il codice più pulito e stabile già sul nascere restituendoci il tempo
speso all'inizio perché i test di collaudo vengono già applicati
progressivamente in
produzione, il codice con questa tecnica sarà funzionale e pulito e i benefici
sono più evidenti se si pensa ad un progetto esteso di vari programmatori
ognuno dedicato ad un suo modulo per poi raggruppare il tutto in un unica
soluzione.

