Perché è necessario specificare il tipo di dati quando si dichiarano le variabili?


41

Nella maggior parte dei linguaggi di codifica (se non tutti) è necessario dichiarare le variabili. Ad esempio in C # se è un campo numerico allora

int PhoneNumber

Se sto usando la normale lingua inglese non ho bisogno di dichiarare PhoneNumbercome intusarla. Ad esempio, se chiedo al mio amico Sam di darmi il suo numero di telefono, dico:

"Sam dammi il numero di telefono"

Non direi

"Char (20) Sam dammi il numero di telefono int"

Perché dobbiamo specificare il tipo di dati?


83
Questo perché l'inglese ha una digitazione implicita - quindi yourPhoneNumber è implicitamente digitato come PhoneNumber - gli umani hanno anche un'allocazione dinamica della memoria ...;)
HorusKol

28
Tu e Sam sapete che un numero di telefono è composto da cifre e sarete sorpresi di trovarvi una lettera. I computer no e devono essere informati.
Thorbjørn Ravn Andersen,

16
E quando sento numeri come 1-800-JIMBO nei film, il mio pensiero è: come è un numero ? Oo
muru,

103
Non dovresti dichiarare phoneNumber come int. Nella maggior parte dei linguaggi di programmazione questo eliminerà gli zeri iniziali.
Aron_dc,

25
@HorusKol: gli umani non hanno solo un'allocazione dinamica della memoria, ma anche un garbage collector altamente non conservativo ...
leftaroundabout

Risposte:


79

Nella maggior parte dei linguaggi di codifica (se non tutti) è necessario dichiarare le variabili.

[...]

Perché dobbiamo specificare il tipo di dati?

Queste sono due domande indipendenti:

  • Perché dobbiamo dichiarare le variabili?
  • Perché dobbiamo dichiarare i tipi?

Per inciso, la risposta ad entrambi è: noi no.

Esistono molti linguaggi di programmazione tipicamente statici in cui non è necessario dichiarare i tipi. Il compilatore può dedurre i tipi dal contesto circostante e dall'uso.

Ad esempio, in Scala puoi dire

val age: Int = 23

o potresti semplicemente dire

val age = 23

I due sono esattamente equivalenti: il compilatore dedurrà il tipo Intdall'espressione di inizializzazione 23.

Allo stesso modo, in C♯, puoi dire uno di questi, ed entrambi significano esattamente la stessa cosa:

int age = 23;
var age = 23;

Questa funzione si chiama inferenza di tipo e molte altre lingue oltre a Scala e C♯ ce l'hanno: Haskell, Kotlin, Ceylon, ML, F♯, C ++, tu lo chiami. Anche Java ha forme limitate di inferenza di tipo.

Nei linguaggi di programmazione tipizzati dinamicamente, le variabili non hanno nemmeno tipi. I tipi esistono solo dinamicamente in fase di esecuzione, non staticamente. Solo i valori e le espressioni hanno tipi e solo in fase di esecuzione, le variabili non hanno tipi.

Ad esempio in ECMAScript:

const age = 23;
let age = 23;

E infine, in molte lingue, non è nemmeno necessario dichiarare le variabili. ad es. in Ruby:

age = 23

In realtà, quell'ultimo esempio è valido in numerosi linguaggi di programmazione. La stessa identica riga di codice funzionerebbe anche in Python, per esempio.

Così,

  • anche nelle lingue tipicamente statiche in cui le variabili hanno tipi, non è necessario dichiararle necessariamente,
  • nelle lingue tipizzate dinamicamente, le variabili non hanno tipi, quindi ovviamente non puoi nemmeno dichiararle,
  • in molte lingue, non è nemmeno necessario dichiarare le variabili

2
Più uno per spiegare sia l'inferenza del tipo che la digitazione dinamica (associazione tardiva)
dal

36
Questa è una grande informazione su idee sbagliate dietro la domanda, ma lascia ancora la domanda senza risposta. La domanda, più propriamente, è perché dobbiamo specificare il tipo di dati quando dichiariamo variabili in lingue che lo richiedono? Perché sono stati progettati in modo? Ci sono buone risposte a questa domanda, e mentre l'elaborazione di alternative allarga gli orizzonti del PO ed è molto buona, questo non mi sembra completo.
KRyan,

7
@KRyan: se vuoi sapere perché un determinato designer di lingue ha fatto una certa scelta nel design del linguaggio, dovrai chiedere a quel designer di linguaggi, temo. Non posso dirti perché i progettisti di C♯ abbiano deciso di non dedurne l'inferenza, né posso dirti perché in seguito hanno cambiato idea. Il design del linguaggio è fortemente supponente e spesso si riduce al gusto. Se, OTOH, vuoi conoscere gli specifici compromessi coinvolti, la risposta sarebbe sostanzialmente una ristampa dei tipi e dei linguaggi di programmazione del Prof. Pierce che è troppo ampia per Stack Exchange.
Jörg W Mittag,

2
JörgWMittag: come già detto da @KRyan, la risposta "non è necessario" non è molto interessante (è banalmente ovvio - molte lingue consentono di omettere le dichiarazioni di tipo in alcuni casi). La domanda "perché vorresti dichiarare i tipi" è molto più interessante e rispecchia meglio lo spirito della domanda originale (la tua risposta mi ricorda lo scherzo: "dove siamo?" - "sei in mongolfiera) ! " ). Non è necessario sapere cosa pensava un designer di un linguaggio specifico al momento, per fornire alcune buone ragioni a favore della dichiarazione del tipo.
jfs,

1
@Zaibis: auto i = 1 // i is inferred to type int, vector<int> vec; auto itr = vec.iterator(); // itr is inferred to type vector<int>::iteratore così via. Se vuoi sapere come funziona esattamente, puoi cercarlo nelle specifiche.
Jörg W Mittag,

53

Quando usi il linguaggio naturale per riferirti alle informazioni, non è molto preciso e, in particolare, non comunica molto agli altri sulle tue intenzioni. Problemi simili si verificano quando si cerca di fare matematica in linguaggio naturale: non è abbastanza preciso.

La programmazione è complessa; gli errori sono fin troppo facili da trovare. I tipi fanno parte di un sistema di controlli progettati per prevenire stati di programma illegali, rilevando condizioni di errore. Lingue diverse usano i tipi in modo diverso: alcune lingue usano pesantemente i tipi per rilevare errori in fase di compilazione. Quasi tutte le lingue hanno una nozione di tipi incompatibili come errore di runtime. Di solito un errore di tipo indica un bug di qualche tipo nel programma. Quando consentiamo ai programmi di continuare nonostante gli errori, probabilmente otteniamo risposte pessime. Preferiamo interrompere il programma piuttosto che ottenere risposte errate o errate.

In altre parole, i tipi esprimono vincoli sul comportamento del programma. I vincoli, se applicati da alcuni meccanismi, forniscono garanzie. Tali garanzie limitano la quantità di ragionamento necessario per pensare al programma, semplificando così il compito di leggere e mantenere il programma per i programmatori. Senza i tipi e le relative implicazioni di strumenti (ovvero il compilatore) che rilevano errori di tipo, l'onere della programmazione è considerevolmente più elevato e quindi più costoso.

È vero che (molti) umani distinguono facilmente tra un numero di telefono europeo, americano e internazionale. Tuttavia, il computer in realtà non "pensa" e, se detto, comporre un numero di telefono degli Stati Uniti in Europa o viceversa. I tipi, ad esempio, sono un buon modo per distinguere tra questi casi, senza dover insegnare al computer come "pensare". In alcune lingue, è possibile che venga visualizzato un errore di compilazione per il tentativo di mescolare un numero di telefono europeo su un sistema telefonico americano. Tale errore ci dice che dobbiamo modificare il nostro programma (magari convertendo il numero di telefono in una sequenza di chiamate internazionali o, invece, utilizzando il numero di telefono in Europa), prima ancora di tentare di eseguire il programma.

Inoltre, poiché il computer non pensa, il nome del campo o della variabile (ad es. phonenumber) Non significa nulla per il computer. Per il computer, quel nome campo / variabile è solo "blah123". Pensa a come sarebbe il tuo programma se tutte le variabili fossero "blahxxx". Yikes. Bene, questo è ciò che vede il computer. Fornire un tipo dà al computer una vaga idea del significato della variabile che semplicemente non può dedurre dal suo solo nome.

Inoltre, come dice @Robert, in molti linguaggi moderni non dobbiamo specificare i tipi come facevamo ai vecchi tempi, poiché linguaggi come C # eseguono "inferenza di tipo", che è un insieme di regole per determinare il tipo corretto per una variabile nel contesto. C # fornisce solo l'inferenza del tipo su variabili locali, ma non su parametri formali o campi di classe o istanza.


4
RE la parte triste: è impossibile dedurre il tipo di un membro accessibile al pubblico (campo pubblico, firma del metodo pubblico), perché non è possibile prevedere quando e come verrà utilizzato. Inoltre, le annotazioni dei tipi sono documentazione.
Sergio Tulentsev,

Penso che dovresti evidenziare / evidenziare questa linea: Types are part of a system of checks that ...poiché risponde direttamente Why do we have to specify data type at all?
all'OP

Nota: la risposta presuppone che un linguaggio utilizzato per specificare i tipi sia in qualche modo migliore per evitare errori rispetto al normale linguaggio di programmazione. Ovviamente non è così, ad esempio, prendere in considerazione un linguaggio modello C ++ che sia Turing completo (e quindi consenta di esprimere molti controlli degli errori) ma è quasi illeggibile rispetto a molti altri linguaggi completi di Turing come Haskell, Python e persino altre parti di C ++ stesso. Chiediti perché non usi lo stesso linguaggio di programmazione per esprimere i controlli degli errori del resto del tuo programma (ci sono buone risposte in alcuni ma non in tutti i casi).
jfs

@SergioTulentsev Questo non è vero - in F #, puoi avere metodi pubblici senza specificarne esplicitamente i tipi. Il compilatore dedurrà i tipi dall'uso all'interno del metodo. Ad esempio, le seguenti sono definizioni di metodo pubblico valide: static member add x y = x + y, member x.Append s = x.Text + s. Nel primo caso, xe yverrà dedotto essere ints a causa dell'aggiunta. Nel secondo caso, saranno comunque validi a seconda del tipo di x.Text- se è un string, allora slo sarà stringanche. Concordo tuttavia sul fatto che le annotazioni sui tipi sono documentazione.
Roujo,

"Tipi locali impliciti, tipi di interfaccia espliciti" è il modo in cui molte persone programmano, anche in lingue come Haskell che ti permettono di omettere (quasi) tutti i tipi pur avendo il compilatore inferire tipi rigorosi. Ci sono molte persone che non lo considerano triste quando una lingua impone questa pratica (come fa C #).
Ben

29

Oltre alle altre risposte, c'è una cosa che dovrebbe essere inclusa. Ricorda che i computer sono solo bit. Di 'che ti do i byte:

26 3A 00 FF

Che cosa significa ? È memorizzato in questo modo dal computer, ma senza alcuna interpretazione, è solo bit . Potrebbe essere composto da 4 caratteri ASCII. Potrebbe essere un numero intero. Potrebbe trattarsi di alcuni byte in un array. Potrebbe far parte di un oggetto. Potrebbe essere un puntatore al punto in cui il video di questo gatto è buffering. Praticamente tutti i linguaggi di programmazione dall'assemblaggio in poi hanno bisogno di qualcosa per sapere come interpretare i bit per farli fare calcoli significativi.

E poiché il computer non è in grado di conoscere il significato di quei bit, ha bisogno che tu lo dica, sia esplicitamente tramite annotazioni di tipo, sia implicitamente tramite meccanismi di inferenza di tipo menzionati nelle altre risposte.


10
Abbastanza vero, ma per confondere davvero la tua mente, renditi conto che il computer non è mai in grado di capire cosa significano quei bit, anche quando dici più annotazioni di tipo. Le tue spiegazioni vengono semplicemente trasformate in ancora più numeri esadecimali, per "chiarire" i primi numeri esadecimali. Il significato è tutto creato dalle persone per mettere l'intenzione nell'elettronica e farle fare ciò che intendiamo. Ora vai a dire "grazie" a un ingegnere. :)
Wildcard

1
Ho trascorso molti anni a programmare su mainframe. Con PL / 1 questa risposta ha molto senso. Abbastanza regolarmente verremmo utilizzati in base alla memoria basata su un puntatore impostato sull'indirizzo di un'altra variabile di un diverso tipo di dati per accedere ai byte in modo diverso. Ad esempio PL / 1 non supporta un campo numerico binario da 1 byte, ma baseremo una variabile di 1 carattere all'indirizzo per consentirci di memorizzare un array di 6 byte che memorizza 6 campi binari a byte singolo (in questo caso consentendoci di salvare 6 byte per indirizzo - che era importante quando lo spazio di archiviazione era costoso).
Calcio d'

1
Il computer è in grado di comprendere molte possibilità, ma anche i compilatori intelligenti hanno bisogno di un contesto per capirlo. Non è lo stesso il numero 0 o "0". Oppure la stringa "31 dic" verrà ordinata prima del "1 maggio" trattata come una stringa ma non se trattata come una data. O prendere 5/2. È 2 come invio ma 2,5 come doppio. Inoltre, il tipo è una misura di sicurezza contro conversioni indesiderate. Anche null, NaN e arrotondamenti o overflow potrebbero diventare un problema. Lingue forti e tipicamente statiche presentano alcuni vantaggi. Ad esempio, il compilatore ti aiuta a rilevare i problemi durante il refactoring.
Borjab,

1
@Borjab Intendevi "È 2 come numero intero "?
Richard Everett,

1
@RichardEverett Sicuramente quello era un lapsus. Grazie ma fino a tardi per modificarlo.
Borjab

23

La risposta al motivo per cui i computer necessitano di queste informazioni ha a che fare con la rappresentazione dei dati .

Il nome del "tipo di dati" è un riferimento a regole che aiutano il computer a memorizzare e recuperare informazioni dal suo stato grezzo di 0 e 1 nella memoria del computer.

Ad esempio, il normale carattere ASCII a 8 bit verrebbe archiviato nella memoria del computer (RAM o disco) come 01000001(il carattere maiuscolo "A", codice ASCII 65) o 00001000(il segno di percentuale) o qualsiasi combinazione di 0 e 1 è in quegli 8 bit.

Per un altro esempio, alcuni numeri interi senza segno a 8 bit possono essere memorizzati come 00000101(il numero 5) o 00001000(il numero 8)

Notare come la rappresentazione binaria di 8 e il carattere% possano essere uguali, ma significano cose diverse perché i loro tipi sono diversi.

Anche le lingue che inferiscono il tipo di dati, potrebbero non avere la regola che "tutti i tipi di variabili devono essere dichiarati dal programmatore", hanno regole come "se la tua serie di caratteri è racchiusa tra virgolette, è una stringa" e molte più regole per ogni tipo di dati.

Quindi anche questi hanno bisogno di tipi di dati per capire cosa significano gli 0 e 1, quindi possono ad esempio fare la funzione di concatenazione di stringhe se provi ad "aggiungere" due caratteri o fai l'aggiunta di numeri interi se stai cercando di aggiungere due numeri interi .

Anche nella tua storia , diciamo che non hai chiesto a Sam il numero di telefono, ma Sam ti dà un pezzo di carta con scritto "1123581321". Non si può essere certi che Sam sia solo un fan dei primi otto numeri di Fibonacci o che sia un numero di telefono. Per indovinare dovrai tenere conto del contesto e degli spunti che hai a disposizione, come forse hai chiesto a Sam un numero di telefono un giorno fa, o la nota dice "Call Me", o se conti le cifre e trovi corrisponde ai modelli della maggior parte dei numeri di telefono. Solo allora sapresti che è un numero di telefono che puoi chiamare e non alcune cifre da inserire in una calcolatrice.

Nota come questi suggerimenti che ti hanno portato a indovinare che il numero era un numero di telefono sono simili a come i suggerimenti portano un linguaggio informatico che non richiede una dichiarazione per dedurre il tipo di un valore.


3
Questa è la risposta più vicina Tutto ha a che fare con la memoria. Dichiarare il tipo in modo che il compilatore sappia quanta memoria deve essere richiesta dall'applicazione in fase di esecuzione. Sapere come interpretare i bit è secondario.
Greg Burghardt,

@GregBurghardt true. Per dare un senso ai bit già presenti e mettere i bit lì al primo posto dopo aver convertito i dati dati in binari in base al tipo di dati.
Peeyush Kushwaha,

10

In alcune lingue, non è necessario specificare il tipo di dati.

Le lingue che supportano l'inferenza di tipo di solito possono capire il tipo di dati dal tuo utilizzo. Per esempio,

var name = "Ali"

viene digitato internamente come una stringa, perché il valore è racchiuso tra virgolette.

Alcune lingue non richiedono neanche di dichiarare la variabile; la variabile viene creata al primo utilizzo. Tuttavia, è considerata una buona pratica dichiarare specificamente le variabili, per una serie di motivi importanti; soprattutto perché farlo meglio esprime il tuo intento.


5
Lo var name = "Ali"stile è in realtà comune per le moderne lingue tipicamente statiche . Nei linguaggi tipicamente statici, il tipo è fisso alla creazione, ma può ancora essere determinato dall'inizializzatore. La definizione di un linguaggio tipizzato in modo dinamico è che i tipi si attaccano ai valori, non alle variabili. L'assegnazione di un valore a una variabile quindi imposta anche il tipo di variabile.
MSalters,

@MSalters: ho apportato una leggera modifica alla formulazione.
Robert Harvey,

5
L'ironia qui è che questo include C # con questa sintassi esatta.
Derek Elkins,

1
@MSalters L'assegnazione di un valore a una variabile quindi imposta anche il tipo di variabile. O che la variabile non ha un tipo intrinseco e che l'interprete tenterà di applicare qualsiasi operazione al valore della variabile. Esistono lingue tipizzate dinamicamente in cui codice come il seguente (Javascript) non sarebbe consentito var x = 5; x = "";perché la prima istruzione fa sì xche il tipo "Numero" sia associato x? Sorta di conflitti con la digitazione dinamica . E se no, quale effetto ha il tipo associato alla variabile, oltre l'associazione del tipo al valore?
Zev Spitz,

1
@ZevSpitz: il primo tipo di sistema non viene digitato in modo dinamico, ma non viene digitato affatto. Il tuo esempio Javascript non è digitato in modo dinamico, proprio perché il tipo Numero non può cambiare. In una lingua tipizzata in modo dinamico, x = "";cambia il tipo di x in stringa, anche se in precedenza era un numero.
Salterio il

9

Perché questo è ciò che specifica il design del linguaggio. Quindi, per rispondere alla tua domanda, dobbiamo guardare l'intento dietro la digitazione esplicita in linguaggi come C # e C ++. (Beh, C # lo fa perché C ++ lo fa perché C lo fa, quindi dobbiamo guardare l'intento fino a quel momento).

Innanzitutto, la digitazione esplicita e statica fornisce rigore nella codifica: specificare una variabile come un numero intero significa che il compilatore e il software devono essere sorpresi e generare un errore quando si assegna un carattere o una stringa alla variabile. La digitazione dinamica può causare mal di testa a chi non lo sa (basta guardare PHP o l'approccio javascripts alla veridicità di cose come array e stringhe vuote).

Puoi avere staticità con la tipizzazione implicita - l'inizializzazione di una variabile come stringa significa che la variabile dovrebbe essere sempre e solo una stringa, ma la mia sensazione è che ciò possa causare problemi agli umani che leggono il codice (tendo ad assumere la digitazione dinamica quando c'è una digitazione implicita ).

Inoltre, è possibile, in alcune lingue, scrivere qualcosa come questo pseudocodice per inizializzare una classe da un input di stringa:

PhoneNumber phoneNumber = "(61) 8 8000 8123";

In secondo luogo, anche la digitazione esplicita va di pari passo con l'allocazione della memoria. Un int è sempre così tanti byte. Un PhoneNumber è così tanti byte. Il compilatore può assegnare un blocco di memoria di dimensioni adeguate che può quindi essere utilizzato in seguito senza dover vedere quanto spazio sarà necessario quando si assegna un valore.

PhoneNumber phoneNumber;
...
phoneNumber = "some value from somewhere";

Infine, rimuove la confusione ... 123 è un numero intero o un numero intero senza segno? Hanno bisogno dello stesso numero di byte, ma il valore massimo memorizzato in variabili di entrambi i tipi è molto diverso ...

Ciò non significa che esplicito sia meglio di implicito, ma il design del linguaggio si basa su questo tipo di scelte e C # funzionerebbe diversamente con la tipizzazione implicita. PHP e javascript funzionerebbero diversamente con la digitazione esplicita.


5

Perché Sam è più intelligente dei compilatori. Ad esempio, quando dici che mi dai il numero di telefono, non specifichi se vuoi il prefisso del paese o il prefisso se si tratta del numero di lavoro in cui sono richieste solo le ultime 4 cifre. Inoltre, se chiedi il numero della pizzeria locale, potresti avere a che fare con la risposta "pizza4u".

Sam, lo capisce dal contesto. Mentre il compilatore può anche capirlo dal contesto, Sam sarà più bravo a farlo (ed è in grado di interrompere il processo per chiedere chiarimenti).

Esistono due approcci di base a tipi e variabili, o la variabile ha un tipo, nel qual caso le azioni che non sono consentite dal tipo sono vietate e impediscono la compilazione, oppure il valore ha un tipo e azioni che non sono consentite dal il tipo viene catturato in fase di esecuzione.

Ogni approccio ha i suoi vantaggi e svantaggi. In generale, gli autori di compilatori cercano di ridurre al minimo gli svantaggi e massimizzare i vantaggi. Ecco perché C #, ad esempio, consente var phoneNumber = GetPhoneNumber();e dedurrà il tipo di phoneNumber dalla firma di GetPhoneNumber. Ciò significa che devi dichiarare il tipo per il metodo, ma non la variabile che riceve il risultato. D'altra parte, ci sono vari tipi di progetti di suggerimento / applicazione per javascript. Tutto è un compromesso.


3

È una questione di come vengono archiviati i dati. La tua interazione con Sam farebbe un paragone migliore se te lo chiedessi in modo da poterlo scrivere, ma aveva solo carta di otto caratteri.

"Sam, dammi il numero di telefono."

"5555555555"

"Oh no, ho esaurito la carta. Se solo avessi saputo in anticipo quanti dati avrei chiesto avrei potuto preparare meglio!"

Quindi, invece, molte lingue ti fanno dichiarare un tipo, così saprà e preparerà in anticipo:

"Sam, quanto dura un numero di telefono?"

"Dieci personaggi."

"Ok, allora fammi prendere un pezzo di carta più grande. Ora dammi il numero di telefono."

"5555555555"

"Capito! Grazie Sam!"

Diventa ancora più peloso se osservi i modi fondamentali effettivi in ​​cui i dati vengono archiviati. Se sei come me, hai un quaderno con note varie, numeri appena scritti, nessun contesto o etichettatura per nulla, e non hai idea di cosa significhi qualcosa tre giorni dopo. Questo è un problema anche per i computer molte volte. Molte lingue hanno tipi "int" (int, long, short, byte) e "float" (float, double). Perché è necessario?

Bene, prima diamo un'occhiata a come viene memorizzato un numero intero, e generalmente rappresentato all'interno del computer. Probabilmente sei consapevole che a livello base è tutto binario (1 e 0). Binario è in realtà un sistema numerico che funziona esattamente come il nostro sistema numerico decimale. In decimale, conti da 0 a 9 (con infiniti zeri iniziali impliciti che non scrivi), quindi torna indietro a 0 e incrementa la cifra successiva in modo da avere 10. Ripeti finché non passi da 19 a 20, ripetere fino a quando non si passa da 99 a 100 e così via.

Binario non è diverso, tranne per il fatto che invece di 0 a 9, si contano da 0 a 1. 0, 1, 10, 11, 100, 101, 110, 111, 1000. Quindi, quando si digita 9, nella memoria registrata in binario come 1001. Questo è un numero reale. Può essere aggiunto, sottratto, moltiplicato, ecc. Esattamente in quella forma. 10 + 1 = 11. 10 + 10 = 100 (passa da 1 a 0 e porta il 1). 11 x 10 = 110 (e equivalentemente, 11 + 11 = 110).

Ora nella memoria effettiva (registri inclusi), c'è un elenco, un array, qualunque cosa tu voglia chiamarlo, di bit (potenziali 1 o 0 ') uno accanto all'altro, che è come mantiene questi bit organizzati logicamente per creare un numero maggiore di 1. Il problema è che cosa fai con i decimali? Non puoi semplicemente inserire un pezzo di hardware tra i due bit nel registro e costerebbe troppo aggiungere "bit decimali" tra ogni coppia di bit. Quindi che si fa?

Lo codifichi. Generalmente, l'architettura della CPU o del software determinerà come farlo, ma un modo comune è quello di memorizzare un segno (+ o -, generalmente 1 è negativo) nel primo bit del registro, una mantissa (il tuo numero spostato tuttavia molte volte deve essere necessario eliminare il decimale per il seguente numero X di bit e un esponente (il numero di volte in cui è stato necessario spostarlo) per il resto. È simile alla notazione scientifica.

La digitazione consente al compilatore di sapere cosa sta guardando. Immagina di aver memorizzato il valore 1.3 nel registro 1. Troveremo qui il nostro schema di codifica fantasia, 1 bit per segno, 4 per mantissa, 3 per esponente (1 bit per segno, 2 per grandezza). Questo è un numero positivo, quindi il segno è positivo (0). La nostra mantissa sarebbe 13 (1101) e il nostro esponente sarebbe -1 (101 (1 per negativo, 01 = 1)). Quindi memorizziamo 01101101 nel registro 1. Ora non abbiamo digitato questa variabile, quindi quando il runtime lo usa, dice "certo, questo è un numero intero perché no" quindi quando stampa il valore vediamo 109 (64 + 32 + 8 + 4 + 1), che ovviamente non è giusto.

Tuttavia, non tutte le lingue richiedono di digitare esplicitamente. C # ha una parola chiave "var" che fa interpretare il tipo di una variabile al momento della compilazione, e altre lingue come Javascript sono tipizzate in modo totalmente dinamico, al punto che è possibile memorizzare un numero intero in una variabile, quindi assegnarlo a un valore booleano, quindi assegnarlo di nuovo a una stringa e la lingua tiene traccia di tutto.

Ma è molto più facile per il compilatore, l'interprete o il runtime - e spesso si traduce in un programma più veloce poiché non deve spendere risorse preziose per ordinare attraverso la digitazione di tutto - per chiedere a te, al programmatore, che tipo di dati che stai fornendo.


2

Esistono linguaggi di programmazione in cui non è necessario dichiarare i tipi di dati per le variabili. Esistono persino linguaggi di programmazione in cui non è necessario dichiarare prima le variabili; si può semplicemente utilizzare loro, subito.

Il problema di non dichiarare i nomi delle variabili è che se si scrive erroneamente il nome di una variabile, ora si è accidentalmente creata una nuova variabile completamente non correlata. Quindi, quando esegui il tuo programma, non riesci a capire perché diavolo quella variabile che hai impostato improvvisamente non abbia nulla in esso ... Fino a quando, dopo molte ore di debug, ti rendi conto di aver digitato il maledetto nome sbagliato! GRRR !!

Quindi ce l'hanno fatta, quindi devi dichiarare prima i nomi delle variabili che userai. E ora quando si digita un nome errato, si ottiene un errore di compilazione, che ti dice immediatamente esattamente dove si trova il bug, prima ancora che il programma venga eseguito. Non è molto più facile?

Stesso affare con i tipi di dati. Esistono linguaggi di programmazione in cui non è necessario dichiarare che tipo di cose dovrebbero essere. Se hai una customervariabile che in realtà è solo il nome di un cliente, non l'intero oggetto cliente, provare a recuperare l'indirizzo del cliente da una semplice stringa ordinaria ... non funzionerà. L'intero punto della digitazione statica è che il programma non verrà compilato; si lamenterà ad alta voce, indicando il luogo esatto in cui si trova il problema. È molto più veloce dell'esecuzione del codice e del tentativo di capire perché diavolo non funziona.

Tutte queste sono caratteristiche per dire al compilatore cosa avresti intenzione di fare, in modo da poter controllare cosa hai effettivamente fatto e assicurarti che abbia senso. Ciò consente al compilatore di individuare automaticamente i bug per te, il che è un grosso problema.

(Nel lontano passato, non dovevi dichiarare i sottoprogrammi . Avresti solo GOSUBun determinato numero di riga. Se avessi voluto passare informazioni tra i sottoprogrammi, avresti impostato particolari variabili globali, chiamato la tua subroutine e poi ispezionato variabili quando la subroutine ritorna, ma ciò rende spaventosamente facile dimenticare di inizializzare uno dei parametri. Quindi ora quasi tutti i linguaggi di programmazione moderni richiedono che tu dichiari quali parametri effettivi prende una subroutine, quindi possiamo verificare di averli specificati tutti. )


1
In C ++ puoi inserire "auto x = 1" e sa che è un int. auto y = 1.2; auto z = 'Z'; ecc.
QuentinUK

@QuentinUK In C #, puoi ottenere var x=1risultati simili. Ma non è niente; in Haskell, puoi scrivere tutto il tuo programma senza firme di tipo, ma è tutto staticamente tipizzato e ricevi ancora errori se commetti un errore ... (Non esattamente mainstream però.)
MathematicalOrchid

@QuentinUK Ma se si scrive for (auto i=0; i<SomeStdVector.size(); ++i)il tuo linter sta andando a lamentarsi perché dedotto un firmato tipo e si procede per confrontarlo con un tipo senza segno. Devi scrivere auto i=0ul(inserendo nuovamente le informazioni sul tipo in modo esplicito, quindi dovresti semplicemente scrivere size_t i=0in primo luogo).
dmckee,

1

Se sto usando la normale lingua inglese, non ho bisogno di dichiarare PhoneNumber come int per usarlo. Ad esempio, se chiedo al mio amico Sam di darmi il suo numero di telefono, dico:

"Sam dammi il numero di telefono"

Non direi>

"Char (20) Sam dammi il numero di telefono int"

Perché dobbiamo specificare il tipo di dati?

Fai un salto su MathOverflow o Theoretical Computer Science e leggi per un po 'di tempo per avere un'idea di come gli umani abbiano comunicato gli alogritmi tra loro quando vogliono assicurarsi che non ci siano possibilità di incomprensioni. Oppure leggi lo standard per un linguaggio di programmazione maturo.

Scoprirai che la definizione di quali tipi di valori sono ammessi a un termine fa parte di una pratica di comunicazione davvero precisa anche da uomo a uomo.

Quello che hai notato è che le interazioni quotidiane sono abbastanza regolari e l'uomo è abbastanza tollerante ai guasti, quindi un malinteso sui numeri di telefono è generalmente evitato dalla conoscenza condivisa dei partecipanti.

Ma hai mai provato a prendere un numero di telefono per qualcuno in un altro paese? Ti hanno detto esplicitamente quante volte spingere zero per arrivare agli indirizzi internazionali? Ti hanno detto il loro prefisso internazionale? L'hai riconosciuto come tale? Quante cifre ti aspettavi? Quanti ne hai presi? Sapevi come raggruppare le cifre? O anche se il raggruppamento ha un significato?

Improvvisamente il problema è molto più difficile e probabilmente hai prestato molta più attenzione a verificare esplicitamente che il numero ricevuto fosse compreso nel modo in cui il mittente lo intendeva.


0

Un altro motivo per dichiarare i tipi è l'efficienza. Mentre un numero intero può essere memorizzato in 1 byte, o 2 byte o 4, un programma che utilizza un numero molto elevato di variabili potrebbe utilizzare 4 volte la memoria necessaria, a seconda di ciò che viene fatto. Solo il programmatore sa se uno spazio di archiviazione più piccolo è praticabile, quindi può dirlo dichiarando il tipo.

Inoltre, gli oggetti tipizzati dinamicamente consentono molti tipi possibili, al volo. Ciò potrebbe comportare un certo sovraccarico "sotto il cofano", rallentando il programma rispetto a rimanere sempre con un tipo.


0

Un numero di linguaggi di programmazione precoci (in particolare Fortran) non richiedeva la dichiarazione di variabili prima dell'uso.

Ciò ha comportato una serie di problemi. Uno davvero ovvio è che il compilatore non può più rilevare errori tipografici altrettanto affidabili. Se hai un codice che dovrebbe modificare una variabile esistente, ma ha un refuso, hai ancora un codice perfettamente legittimo che ha appena creato (e assegnato un valore a) una nuova variabile:

longVariableName = 1

// ...

longVaraibleName = longvariableName + anotherLongVariableName

Ora, guardando questo in isolamento, con il mio già menzionato un refuso come fonte del problema, probabilmente è abbastanza facile trovare l'errore e il problema qui. In un lungo programma, in cui questo è sepolto nel mezzo di molti altri codici, è molto più facile perdere.

Anche attualmente con molte lingue tipizzate dinamicamente, puoi ancora ottenere lo stesso problema di base abbastanza facilmente. Alcuni hanno qualche possibilità di avvisarti se ti assegni a una variabile, ma non la leggono mai (che euristicamente rileva un bel po 'di problemi come questo) entrambi gli altri non hanno tali cose.


0

Quando si dichiara una variabile, nella memoria viene allocato dello spazio, ma la macchina (in questo caso il computer) non sa già quanto spazio deve essere allocato per quella variabile.

Esempio: - si crea un programma che chiede all'utente di inserire qualsiasi numero, in questo caso è necessario specificare un tipo di dati per memorizzare quel numero, altrimenti la macchina non può giudicare da sola che dovrebbe allocare 2 byte o 2 gigabyte , se prova per eseguire l'allocazione da sola, ciò può comportare un uso inefficiente della memoria. D'altra parte, se si specifica il tipo di dati nel proprio programma, dopo la compilazione la macchina assegnerebbe lo spazio adeguato in base alle necessità.


questo non sembra offrire nulla di sostanziale rispetto ai punti formulati e spiegati nelle precedenti 11 risposte
moscerino del

1
Gnat, dovresti leggere ancora una volta tutte le risposte e vedere che ho cercato di rispondere a questa domanda in un modo molto più semplice che puoi facilmente capire.
Atul170294,

Ho appena ricontrollato le tre risposte più recenti pubblicate circa un'ora prima di questa e tutte e tre sembrano fare lo stesso punto e per la mia lettura lo spiego in un modo più semplice di qui
moscerino del

Anche se non ho risposto per la ricompensa del tuo voto, ma penso che dovresti conoscere una cosa, dovresti sottovalutare una risposta perché potrebbe dare informazioni inutili o sbagliate e se contiene qualcosa di offensivo. Tutte le risposte che hanno le informazioni più utili e pertinenti otterranno un numero maggiore di voti che è sufficiente per distinguere tra una risposta, una buona e la migliore. La tua attività infantile di downvoting di una risposta senza validi motivi scoraggerà solo altre persone che vogliono anche condividere la loro opinione che ritengono possa essere utile ad altri
Atul170294

1
Molto probabilmente la tua risposta è stata sottoposta a downgrade perché non è corretta. La digitazione statica non è necessaria per la gestione della memoria. Esistono molte lingue che consentono la digitazione dinamica e quelle lingue / ambienti sono in grado di gestire i problemi di gestione della memoria citati.
Jay Elston,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.