La maggior parte dei linguaggi di programmazione ha un concetto noto come "tipo", implementato tramite un "sistema di tipi".
Quando un programmatore scrive un programma, generalmente dichiara un insieme di variabili e poi scrive un codice sorgente che dice al computer di fare qualcosa con le variabili. Ogni variabile, quando dichiarata, è associata a un tipo, come numero intero, byte o stringa. Il tipo determina come il compilatore interpreterà il codice sorgente che lavora con le variabili, che determinerà quale tipo di codice macchina emettere durante la compilazione.
Ad esempio, in c #, se voglio aggiungere o sottrarre due numeri, potrei scrivere:
int a = 2;
int b = 2;
int c = a + b;
int d = a - b;
In questo codice, ho detto c # che voglio quattro posizioni di memoria e voglio che vengano trattati come numeri interi. Sulla terza riga, posso usare l'operatore +
su a
e b
perché l'aggiunta è consentita per i numeri interi. E sulla quarta riga posso usare -
.
Se volessi lavorare con le stringhe, potrei scrivere invece:
string a = "2";
string b = "2";
string c = a + b;
string d = a - b; //Error
In questo esempio, ho detto c # per impostare quattro posizioni di memoria e trattarle come stringhe. Alla riga 3 posso aggiungerli insieme perché l'aggiunta è valida per le stringhe (le concatenerà). Ma sulla quarta riga il compilatore mi dirà che ho fatto un errore, perché la sottrazione non è consentita per le stringhe, dal momento che non è esattamente chiaro cosa farebbe se fosse permesso.
Allo stesso modo ci sono tipi di dati per date, orari, numeri in virgola mobile e strutture complesse. Inoltre, un programmatore può spesso definire i propri tipi, come oggetti, che possono essere programmati per rappresentare concetti di business, connessioni di database o altre strutture più avanzate, che richiedono una posizione di memoria per l'archiviazione, ma hanno regole diverse per come per leggere quelle posizioni di memoria.
In alcuni rari casi è possibile copiare i dati di un tipo in una variabile di un altro tipo. Questo in genere non è consentito nelle lingue di tipo "sicuro" perché i dati potrebbero essere interpretati erroneamente. Ma in linguaggi come assembly e c, puoi farlo, e di solito devi stare molto attenti a non causare problemi.
Ora che mi dici del codice? Bene, il codice è solo un'altra locazione di memoria, e anch'essa riceve un nome ("simbolo"), noto come punto di ingresso:
static void main()
{
int a = 2;
int b = 2;
int c = a + b;
int d = a - b;
}
Nell'esempio sopra, dichiaro una posizione di memoria con un punto di ingresso chiamato "main". Questa posizione di memoria conterrà le istruzioni per riservare la memoria per a
, b
, c
e d
, e conterrà le istruzioni per impostarle su 2 e per eseguire i calcoli matematici. Quando scrivo codice sorgente che chiama main
, il compilatore emetterà un codice leggibile dalla macchina che punta il puntatore all'istruzione al punto di ingresso main
, dove eseguirà le istruzioni. Quindi non c'è mai alcun mix tra codice e dati, e il computer (si spera) non tenterà mai di eseguire un numero o provare a fare matematica sul codice.