Linguaggio C

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.

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;


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.

Vai al sito  >>>
    Carmine Romano