C (AFI: ) è un linguaggio di programmazione a uso generale di natura imperativa e procedurale creato da Dennis Ritchie negli anni 1970. Tutt'oggi influente, è largamente adoperato nei sistemi operativi, nei driver e nelle pile di protocolli, mentre è in diminuzione il suo uso nelle applicazioni. C è comunemente usato in architetture che vanno dai più grandi supercalcolatori fino ai minuscoli microcontrollori e sistemi integrati.
Successore del linguaggio B, C fu in origine sviluppato ai Bell Labs da Ritchie tra il 1972 e il 1978 per costruire utilità eseguibili su Unix, e fu subito dopo applicato nella reimplementazione del kernel di quel sistema operativo. Durante gli anni 1980, C gradualmente crebbe in popolarità, diventando nel terzo millennio uno dei linguaggi più usati in assoluto, con compilatori disponibili per praticamente ogni architettura e sistema operativo moderni. Il libro intitolato The C Programming Language, scritto dal suo creatore insieme a Brian Kernighan, servì per molti anni come lo standard de facto del linguaggio. Dal 1976, C è normato dall'American National Standards Institute (ANSI) e dall'International Organization for Standardization (ISO).
C è un linguaggio procedurale imperativo, che supporta la programmazione strutturata, la visibilità lessicale e la ricorsione, e possiede un sistema di tipi statico. Il linguaggio C permette l'utilizzo a basso livello alla memoria e fornisce costrutti che combaciano efficientemente con le istruzioni del linguaggio macchina. Nonostante le sue capacità a basso livello, il linguaggio è adatto per essere programmato su piattaforme diverse: un programma in C conforme scritto per essere portabile può essere compilato per una vasta gamma di piattaforme con poche variazioni al suo codice sorgente.
A partire dal 2000, C è costantemente classificato tra i primi due linguaggi nell'indice TIOBE, una misura di popolarità dei linguaggi di programmazione.
Storia Il linguaggio fu originariamente sviluppato da Dennis Ritchie presso i Bell Labs della AT&T tra il 1969 e il 1973, con lo scopo di utilizzarlo per la stesura del sistema operativo UNIX, precedentemente realizzato da Ken Thompson e Ritchie stesso in assembly del PDP-7. Nel 1972 esordì il primo sistema UNIX su un DEC PDP-11, scritto interamente col nuovo linguaggio di programmazione C. Nel 1978, la pubblicazione del libro Il linguaggio C ne fece crescere rapidamente la diffusione, portando alla nascita di diversi dialetti e dunque alla necessità di definire uno standard.
La prima standardizzazione di C fu realizzata dall'ANSI nel 1989 (ANSI X3.159-1989), nota come C89. La stessa versione, solo con modifiche di formattazione minime, fu poi standardizzata anche dall'ISO nel 1990 (ISO/IEC 9899:1990), nota come C90. Successivamente l'ISO ha pubblicato altre quattro versioni del linguaggio C, note come C95 (ISO/IEC 9899/AMD1:1995), C99 (ISO/IEC 9899:1999), C11 (ISO/IEC 9899:2011/Cor 1:2012) e C18 (ISO/IEC 9899:2018). Di queste, la C99 ha portato i principali miglioramenti al linguaggio di programmazione, introducendo nuovi tipi di dato, gli inizializzatori designati per gli array, gli array di dimensione variabile e altri miglioramenti mutuati da C++.
Funzionalità introdotte nelle revisioni del linguaggio C99 Il tipo di dato , che ammette la memorizzazione dei booleani e ; Il tipo di dato per la rappresentazione dei numeri complessi; Il tipo di dato per la rappresentazione dei numeri immaginari; Il tipo di dato ; Il tipo booleano in <stdbool.h>; Le funzionalità addizionali floating-point in <float.h>; I commenti su linea singola introdotti da ; Le funzioni ; Il qualificatore di tipo , ammissibile solo sui puntatori (restricted pointer); È rimosso l' implicito di ritorno; La lunghezza variabile dell'array (VLA, variable-length array); I letterali composti (Compound literals); Gli inizializzatori designati (Designated initializers) È ammesso dichiarare variabili ovunque si desidera nell'ambito di un blocco di codice così come frapporre tra di esse altre istruzioni; Le funzioni della famiglia vscanf; Le regole per le costanti di tipo intero; Le regole di promozione degli interi (integer promotion); Le macro matematiche di tipo generico in <tgmath.h>; Le macro con un numero variabile di argomenti; La macro va_copy; Lo specificatore di conversione nella funzione printf(); Il supporto all'aritmetica IEEE Floating-Point (IEC 559); L'operatore di preprocessing .
C11 Lo standard C11 ha introdotto cinque nuovi file header, ovvero <stdalign.h>, <stdatomic.h>, <stdnoreturn.h>, <threads.h> e <uchar.h>, nonché diverse funzionalità che hanno contribuito a migliorare il linguaggio:
Le macro inerenti alle specifiche di allineamento della memoria, con il relativo file header <stdalign.h> , tra cui e , nonché la funzione aligned_alloc (Memory Alignment Control); Aggiunto il supporto al multithreading. Le nuove funzionalità sono fornite dalla libreria dei thread dichiarata nel file header <threads.h>. Aggiunto anche il qualificatore di tipo nell'header file <stdatomic.h>; Le strutture () e le unioni () anonime; Espressioni di tipo generico mediante la parola chiave (type-generic expressions); Migliorato il supporto Unicode con i tipi di dato char16_t (UTF-16) e char32_t (UTF-32) con le relative funzioni di conversione dichiarate in <uchar.h>; Rimossa la funzione gets() dichiarata in <stdio.h>; Lo specificatore applicabile alle funzioni; Le asserzioni statiche mediante la parola chiave (Static Assertions); La funzione quick_exit per la terminazione di un programma; Bounds-checking interfaces (specificate nella sezione opzionale "Annex K" del C11); Analyzability features (specificate nella sezione opzionale "Annex L" del C11); La modalità esclusiva x di apertura e creazione file (Exclusive create-and-open mode): Le macro per la creazione di numeri complessi in <complex.h>.
Descrizione Nato insieme a Unix, C è supportato dalla totalità dei sistemi operativi di largo uso impiegati ed è impiegato principalmente per la realizzazione di sistemi operativi, linguaggi di programmazione, librerie, giochi e per applicazioni altamente performanti; è rinomato per la sua efficienza e 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 poi 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, è stato a lungo il linguaggio dominante in tutta una serie di altri domini applicativi caratterizzati mirati sull'efficienza. Esempi tipici sono le telecomunicazioni, il controllo di processi industriali e il software sistema real-time. Il predominio di C in questi contesti è in parte diminuito a seguito dell'avvento di alternative significative, primo fra tutti C++.
C ha anche una notevole importanza didattica, sebbene, per la sua complessità semantica e per le forti relazioni di tale semantica con il funzionamento dell'hardware dei computer, non si tratti di un linguaggio particolarmente intuitivo per i principianti e, in special modo, per quelli sprovvisti di un'adeguata preparazione riguardante l'architettura dei calcolatori. Se un tempo le scuole superiori e i corsi universitari adottavano C come linguaggio di riferimento a causa della sua importanza tecnica, oggi questa scelta trova un'ulteriore motivazione nella crescente importanza di linguaggi che da C derivano (per esempio C++, Java e C# e, per consentire allo studente un approccio iniziale più rapido e intuitivo, linguaggi ad alto livello come Python).
Caratteristiche generali C è un linguaggio di programmazione relativamente minimalista; la sua semantica utilizza un insieme ristretto di concetti relativamente semplici e vicini al funzionamento dell'hardware dei calcolatori. Molte istruzioni C sono traducibili direttamente con una singola istruzione di linguaggio macchina (per esempio, gli operatori di autoincremento e autodecremento). Nel linguaggio, un ruolo centrale viene svolto dal concetto di puntatore, che viene generalizzato fino a coincidere con l'indirizzamento indiretto, un modo di accedere alla memoria hardware caratteristico di tutte le moderne CPU. Questo rende C un linguaggio particolarmente efficiente. Inoltre, rispetto al linguaggio assembly, C ha in più una struttura logica definita e leggibile, funzioni in stile Pascal e soprattutto il controllo sui tipi (in fase di compilazione), che manca completamente nel linguaggio assembly.
La sintassi di C è piuttosto versatile e il linguaggio è in forma libera, permettendo di scrivere istruzioni complesse in poche righe di codice o di creare programmi criptici e illeggibili (offuscamento del codice). In definitiva, il successo di C fu decretato dall'essere un linguaggio creato da programmatori esperti, per essere usato da programmatori esperti.
Questa grande libertà, la complessità sintattica del linguaggio (che come abbiamo visto contiene poche istruzioni di base) e il ruolo centrale dei puntatori, che è necessario usare praticamente fin dai primi programmi, lo rendono quindi un linguaggio ostico e sconsigliabile ai neofiti, che cadono quasi subito in una serie di trappole che, se pure ovvie per un esperto, sono molto difficili da individuare per un principiante.
Grazie alla particolare efficienza del codice prodotto dai suoi compilatori, C venne utilizzato per riscrivere la maggior parte del codice del sistema UNIX, riducendo l'uso del linguaggio assembly ad un piccolo gruppo di funzioni. La sua importanza tuttavia, crebbe solo dopo il 1978 con la pubblicazione, da parte di Brian Kernighan e Dennis Ritchie, del libro The C Programming Language, nel quale il linguaggio venne definito in modo preciso per la prima volta.
Il suo successivo larghissimo utilizzo portò alla nascita di diversi dialetti e quindi alla necessità di definirne uno standard. A questo scopo, nell'estate del 1983, venne nominato un comitato con il compito di creare uno standard ANSI (American National Standards Institute) che definisse il linguaggio C una volta per tutte. Il processo di standardizzazione, il quale richiese sei anni (molto più del previsto), terminò nel dicembre del 1989 e le prime copie si resero disponibili agli inizi del 1990. Questa versione di C è normalmente chiamata C89. Lo standard venne anche adottato dall'International Organisation for Standardisation (ISO) nel 1999 con il nome di C Standard ANSI/ISO. Nel 1995, fu adottato l'Emendamento 1 al C Standard che, fra le altre cose, ha aggiunto nuove funzioni alla libreria standard del linguaggio. Usando come documento base il C89 con l'Emendamento 1 e unendovi l'uso delle classi di Simula, Bjarne Stroustrup iniziò a sviluppare C++.
Il risultato finale del continuo sviluppo di C fu lo standard promulgato nel 1999, noto come ISO C99 (codice ISO 9899).
Con la versione C11 (2011) vengono lievemente rivisti alcuni comandi, mentre la versione C18 (2018) ha corretto alcune criticità della C11, senza tuttavia introdurre alcuna nuova funzionalità.
Tipi di dato C supporta quattro tipi di dato fondamentali, tutti numerici: , che rappresenta un numero intero; , che rappresenta un carattere (più precisamente, un intero positivo associato a un carattere attraverso un sistema di codifica, solitamente ASCII); , che rappresenta un numero decimale; , che rappresenta un numero decimale con precisione doppia rispetto a ..
Esistono inoltre i seguenti modificatori, che si possono anteporre ai nomi dei tipi interi per cambiarne delle caratteristiche: specifica che l'intero può essere positivo o negativo; specifica che l'intero può essere solo positivo; riduce la memoria assegnata al tipo di dato, restringendo di conseguenza l'intervallo numerico rappresentabile; funziona in maniera opposta, aumentando la memoria e ampliando l'intervallo.