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

41

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

int PhoneNumber

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

"Sam give me the phonenumber"

Non direi

"Char(20) Sam give me the int phoneNumber"

Perché dobbiamo specificare il tipo di dati?

    
posta dick smith 21.03.2016 - 00:11
fonte

13 risposte

79

In most coding languages (if not all) you need to declare variables.

[…]

Why do we have to specify data type at all?

Queste sono due domande indipendenti:

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

Per inciso, la risposta ad entrambi è: non lo facciamo.

Esistono numerosi linguaggi di programmazione tipizzati staticamente in cui non è necessario dichiarare i tipi. Il compilatore può dedurre i tipi dal contesto circostante e dall'utilizzo.

Ad esempio, in Scala puoi dire

val age: Int = 23

oppure potresti solo dire

val age = 23

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

Allo stesso modo, in C♯, puoi dire uno di questi due, e entrambi significano la stessa identica cosa:

int age = 23;
var age = 23;

Questa funzione è chiamata tipo inferenza , e molte lingue oltre a Scala e C♯ hanno: Haskell, Kotlin, Ceylon, ML, F♯, C ++, tu la chiami. Persino Java ha forme limitate di inferenza di tipo.

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

es. in ECMAScript:

const age = 23;
let age = 23;

E infine, in molte lingue, non è nemmeno necessario dichiarare variabili. per esempio. in Ruby:

age = 23

In effetti, quest'ultimo esempio è valido in un certo numero di linguaggi di programmazione. La stessa identica linea di codice funzionerebbe anche in Python, per esempio.

Quindi

  • anche in linguaggi tipizzati staticamente in cui le variabili hanno tipi, non devi necessariamente dichiararle,
  • nelle lingue digitate dinamicamente, le variabili non hanno tipi, quindi ovviamente non puoi anche dichiararle,
  • in molte lingue, non devi nemmeno dichiarare le variabili
risposta data 21.03.2016 - 01:52
fonte
52

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

La programmazione è complessa; gli errori sono troppo facili da trovare. I tipi fanno parte di un sistema di controlli progettati per prevenire stati di programmi illegali, rilevando condizioni di errore. Diverse lingue usano i tipi in modo diverso: alcune lingue usano pesantemente i tipi per rilevare gli 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 permettiamo ai programmi di continuare nonostante gli errori, probabilmente otterremo risposte molto negative. Preferiamo interrompere il programma piuttosto che ottenere risposte sbagliate 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 tipi, e le loro implicazioni di strumenti (cioè il compilatore) che rilevano errori di tipo, il carico di programmazione è considerevolmente più alto e, quindi, più costoso.

È vero che (molti) umani distinguono facilmente tra un numero di telefono europeo, degli Stati Uniti e internazionale. Tuttavia, il computer non "pensa" realmente e, se detto, compone 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, possiamo ottenere un errore in fase di compilazione per provare a mescolare un numero di telefono europeo su un sistema telefonico americano. Questo errore ci dice che dobbiamo modificare il nostro programma (magari convertendo il numero di telefono in una sequenza di composizione internazionale, o, usando 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 esempio phonenumber ), non significa nulla per il computer. Al computer, quel campo / nome della 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 nome.

Inoltre, come dice @Robert, in molti linguaggi moderni non dobbiamo specificare i tipi tanto quanto abbiamo fatto 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 di tipo sulle variabili locali, ma non sui parametri formali o sui campi di classe o istanza.

    
risposta data 21.03.2016 - 01:37
fonte
28

Oltre alle altre risposte, c'è una cosa che dovrebbe essere inclusa. Ricorda che i computer sono solo bit. Dì 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 4 caratteri ascii. Potrebbe essere un numero intero. Potrebbe essere alcuni byte in un array. Potrebbe essere parte di un oggetto. Potrebbe essere un puntatore al punto in cui il video del gatto è in fase di buffering. Praticamente tutti i linguaggi di programmazione dall'assemblaggio in su hanno bisogno di qualcosa per sapere come interpretare i bit per farli fare calcoli significativi.

E dal momento che il computer non può conoscere il significato di quei bit, ha bisogno che tu lo dica - esplicitamente tramite annotazioni di tipo, o implicitamente tramite meccanismi di inferenza di tipo menzionati nelle altre risposte.

    
risposta data 21.03.2016 - 03:32
fonte
22

La risposta a perché i computer hanno bisogno di queste informazioni ha a che fare con Rappresentazione dei dati .

Il nome del "tipo di dati" è un riferimento alle regole che aiutano l'archivio del computer e recuperano le informazioni dal suo stato grezzo di 0 e 1 nella memoria del computer.

Per un esempio, il tuo 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 (la percentuale segno), o qualsiasi combinazione di 0 e 1 in questi 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)

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

Anche le lingue che deducono il tipo di dati, potrebbero non avere la regola che i programmatori "tutti i varibles" devono essere dichiarati dal programmatore ", hanno regole come" se la serie di caratteri è racchiusa tra virgolette, è un stringa "e molte altre regole per ogni tipo di dati.

Quindi anche questi hanno bisogno di tipi di dati per capire cosa significano gli 0 e gli 1, quindi possono ad esempio eseguire la funzione di concatenazione delle stringhe se si tenta di "aggiungere" due caratteri, o aggiungere un numero intero se si sta tentando di aggiungi due numeri interi.

Anche in la tua storia , diciamo che non hai chiesto a Sam il numero di telefono, ma Sam ti dà un pezzo di carta su cui è scritto "1123581321". Non si può essere sicuri che Sam sia solo un fan dei primi otto numeri di Fibonacci, o se si tratta di un numero di telefono. Per fare un'ipotesi dovrai tenere conto del contesto e dei segnali che hai a disposizione, come forse hai chiesto a Sam un numero di telefono un giorno fa, o la nota dice "Chiamami", o se conti le cifre e trovi corrisponde a modelli della maggior parte dei numeri di telefono. Solo allora saprai che è un numero di telefono che puoi chiamare e non alcune cifre che potresti inserire in una calcolatrice.

Nota come questi suggerimenti che ti hanno indotto a supporre che il numero fosse un numero di telefono sono simili a come gli hint portano un linguaggio informatico che non richiede la dichiarazione per dedurre il tipo di valore.

    
risposta data 21.03.2016 - 08:48
fonte
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. Ad esempio,

var name = "Ali"

è scritto internamente come stringa, poiché il valore è racchiuso tra virgolette.

Alcune lingue non richiedono che tu dichiari la variabile; la variabile viene creata quando viene utilizzata per la prima volta. Tuttavia, è considerata una best practice dichiarare in modo specifico le variabili, per un numero di motivi importanti; soprattutto perché farlo esprime meglio le tue intenzioni.

    
risposta data 21.03.2016 - 00:23
fonte
9

Perché è ciò che specifica il design del linguaggio. Quindi, per rispondere alla tua domanda, abbiamo bisogno di guardare l'intento dietro la tipizzazione esplicita in linguaggi come C # e C ++. (Bene, C # lo fa perché C ++ lo fa perché C lo fa, quindi abbiamo bisogno di guardare l'intento di allora).

In primo luogo, la tipizzazione esplicita e statica fornisce il rigore nella codifica - specificare una variabile come un intero significa che il compilatore e il software dovrebbero essere sorpresi e generare un errore quando si assegna un carattere o una stringa alla variabile. La digitazione dinamica può causare mal di testa agli sprovveduti (basta guardare l'approccio PHP o javascript alla verità di cose come array e stringhe vuote).

Si può avere statico con digitazione implicita - inizializzare una variabile come stringa significa che la variabile dovrebbe essere sempre una stringa, ma la mia sensazione è che questo possa causare problemi agli umani che leggono il codice (tendo ad assumere una digitazione dinamica quando è una digitazione implicita).

Inoltre, in alcune lingue è possibile 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 numero di telefono è così tanti byte. Il compilatore può assegnare un blocco di memoria di dimensioni appropriate che può essere successivamente utilizzato 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 intero o un intero senza segno? Hanno bisogno dello stesso numero di byte, ma il valore massimo memorizzato nelle variabili di entrambi i tipi è molto diverso ...

Questo non significa che l'esplicito sia meglio di quello implicito - ma il design del linguaggio si basa su questo tipo di scelte e C # funzionerebbe diversamente con la digitazione implicita. PHP e JavaScript funzionerebbero diversamente con la tipizzazione esplicita.

    
risposta data 21.03.2016 - 01:32
fonte
5

Perché Sam è più intelligente dei compilatori. Ad esempio, quando si dice di darmi il numero di telefono, non si specifica se si desidera il prefisso nazionale o il prefisso se si tratta di un numero di lavoro in cui sono richieste solo le ultime 4 cifre. Inoltre, se tu chiedi il numero della pizzeria locale, saresti in grado di gestire la risposta "pizza4u".

Sam, capisce dal contesto. Mentre il compilatore può anche capirlo dal contesto, Sam sarà migliore (ed è in grado di interrompere il processo per chiedere chiarimenti).

Ci sono 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 consentito dal tipo vengono catturati in fase di runtime.

Ogni approccio ha i suoi vantaggi e svantaggi. In generale, gli scrittori di compilatori cercano di minimizzare gli svantaggi e massimizzare i vantaggi. Ecco perché C # per esempio consente var phoneNumber = GetPhoneNumber(); e dedurrà il tipo di numero di telefono 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 progetti di suggerimento / enforcing di tipo per javascript. Tutto è un compromesso.

    
risposta data 21.03.2016 - 04:06
fonte
3

È una questione del modo in cui i dati vengono archiviati. La tua interazione con Sam farebbe un confronto migliore se lo chiedessi in modo che tu possa scriverlo, ma ha solo un valore di otto caratteri.

"Sam, give me the phoneNumber."

"5555555555"

"Oh no I'm out of paper. If only I had known ahead of time how much data I was asking for I could have prepared better!"

Quindi, la maggior parte delle lingue ti fa dichiarare un tipo, quindi lo saprà e lo preparerà in anticipo:

"Sam, how long is a telephone number?"

"Ten characters."

"Ok, then let me get a bigger piece of paper. Now give me the phoneNumber."

"5555555555"

"Got it! Thanks Sam!"

Diventa ancora più peloso quando si osservano i reali modi fondamentali in cui i dati vengono archiviati. Se sei come me, hai un quaderno con note varie, numeri appena scarabocchiati, nessun contesto o etichetta per nulla, e non hai idea di cosa significhi tre giorni dopo. Questo è un problema anche per i computer. 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 viene rappresentato all'interno del computer. Probabilmente sei consapevole del fatto che a livello di base, è tutto binario (1 e 0). Il binario è in realtà un sistema numerico che funziona esattamente come il nostro sistema numerico decimale. In decimale, contate da 0 a 9 (con gli zeri iniziali impliciti infiniti che non scrivete), quindi tornate indietro a 0 e incrementate la cifra successiva in modo da avere 10. Si ripete fino al rollover da 19 a 20, ripeti fino al rollover da 99 a 100 e così via.

Il binario non è diverso, tranne che invece di 0 a 9, conti 0 a 1. 0, 1, 10, 11, 100, 101, 110, 111, 1000. Quindi quando scrivi 9, nella memoria è registrato 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 in modo equivalente, 11 + 11 = 110).

Ora nella memoria attuale (registri inclusi), c'è una lista, array, qualunque cosa tu voglia chiamare, di bit (potenziali 1 o 0 ') uno accanto all'altro, che è il modo in cui mantiene questi bit logicamente organizzati per fare un numero maggiore di 1. Il problema è, cosa fai con i decimali? Non puoi semplicemente inserire un pezzo di hardware tra i due bit nel registro, e costerebbe troppo per aggiungere "bit decimali" tra ogni coppia di bit. Quindi cosa fare?

Lo codifichi. Generalmente, l'architettura della CPU o del software determinerà come ciò viene fatto, ma un modo comune è di memorizzare un segno (+ o -, generalmente 1 è negativo) nel primo bit del registro, una mantissa (il tuo numero è spostato tutte le volte che deve essere necessario per 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 archiviato il valore 1.3 nel registro 1. Verremo qui con il nostro schema di codifica di fantasia, 1 bit per il segno, 4 per mantissa, 3 per esponente (1 bit per il segno, 2 per la magnitudine). 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 inserito questa variabile, quindi quando il runtime va ad usarlo, dice "sicuro, questo è un numero intero perché no", quindi quando stampa il valore vediamo 109 (64 + 32 + 8 + 4 + 1), che ovviamente non è corretto.

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

Ma è molto più semplice sul compilatore, sull'interprete o sul runtime - e spesso si traduce in un programma più veloce poiché non deve spendere risorse preziose per ordinare la digitazione di tutto - per chiederti, il programmatore, che tipo di dati stai dando.

    
risposta data 21.03.2016 - 18:24
fonte
2

Ci sono linguaggi di programmazione in cui non devono dichiarare tipi di dati per le variabili. Esistono anche linguaggi di programmazione in cui non è necessario dichiarare le variabili prima della mano; puoi usarli immediatamente,

Il problema di non dichiarare nomi di variabili è che se erroneamente digiti il nome di una variabile per errore, ora hai accidentalmente creato una nuova variabile completamente indipendente. Quindi quando esegui il tuo programma, non riesci a capire perché l' inferno che la variabile che hai impostato improvvisamente non abbia nulla in esso ... Finché, dopo molte ore di debug, ti rendi conto che hai digitato i dannati nome sbagliato! GRRR !!

Quindi l'hanno fatto, quindi devi dichiarare i nomi delle variabili che userai prima. E ora quando digiti un nome sbagliato, ottieni un errore in fase di compilazione, che ti dice immediatamente esattamente dove si trova il bug, prima ancora che il tuo programma funzioni. Non è molto più semplice?

Lo stesso accordo con i tipi di dati. Esistono linguaggi di programmazione in cui non devono dichiarare quale tipo dovrebbero essere le cose. Se hai una variabile customer che in realtà è solo il nome di un cliente, non l'intero oggetto cliente, cercando di recuperare l'indirizzo del cliente da una semplice stringa normale ... non funzionerà. L'intero punto della tipizzazione statica è che il programma non verrà compilato; si lamenterà rumorosamente, indicando il luogo esatto in cui si trova il problema. È molto più veloce del tuo codice e cerca di capire perché diavolo non funziona.

Tutte queste sono caratteristiche per dire al compilatore cosa eri intenzione di fare, quindi può controllare cosa ha fatto effettivamente e assicurarsi che abbia senso. Ciò consente al compilatore di automaticamente individuare bug per te, che è un grosso problema.

(Nel lontano passato, non dovevi dichiarare subroutine . Avresti solo GOSUB su un particolare numero di riga. Se volevi passare le informazioni tra le subroutine, dovresti imposta particolari variabili globali, chiama la tua subroutine e poi ispeziona altre 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 di dichiarare quali parametri effettivi viene utilizzato da una subroutine, in modo che possiamo verificare di averli specificati tutti.)

    
risposta data 21.03.2016 - 15:36
fonte
1

If I'm using normal English language I do not need to declare PhoneNumber as int to use it. For example if I ask my friend Sam to give me his phone number I say:

"Sam give me the phonenumber"

I wouldn't say>

"Char(20) Sam give me the int phoneNumber"

Why do we have to specify data type at all?

Passa a MathOverflow o Informatica teorica e leggi per un po 'per avere un'idea di come gli umani hanno comunicato gli alogritmi l'uno con l'altro quando vogliono assicurarsi che non ci sia alcuna possibilità di incomprensione. Oppure leggi lo standard per un linguaggio di programmazione maturo.

Scoprirai che definire quali tipi di valori sono consentiti a un termine è 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 che gli umani sono piuttosto tolleranti ai guasti, quindi un equivoco sui numeri di telefono è generalmente evitato dalla conoscenza condivisa dei partecipanti.

Ma hai mai provato a togliere un numero di telefono a qualcuno in un altro paese? Ti hanno detto esplicitamente quante volte spingere a zero per arrivare all'indirizzamento internazionale? Ti hanno detto il loro codice paese? Lo hai riconosciuto come tale? Quante cifre ti aspettavi? Quanti ne hai ricevuti? Sapevi come raggruppare le cifre? O anche se il raggruppamento ha significato?

All'improvviso il problema è molto più difficile e probabilmente hai preso molta più cura di controllare esplicitamente che il numero ricevuto fosse compreso nel modo in cui il mittente intendeva farlo.

    
risposta data 22.03.2016 - 06:47
fonte
0

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

Inoltre, gli oggetti digitati dinamicamente consentono molti tipi possibili, al volo. Ciò potrebbe comportare un sovraccarico "sotto il cofano", rallentando il programma rispetto al fatto di rimanere con un tipo per tutto il tempo.

    
risposta data 21.03.2016 - 18:55
fonte
0

Un certo numero di linguaggi di programmazione iniziali (specialmente Fortran) non richiedeva la dichiarazione delle variabili prima dell'uso.

Ciò ha portato a una serie di problemi. Uno veramente ovvio è che il compilatore non riesce più a cogliere errori tipografici semplici quasi in modo affidabile. Se hai un codice che dovrebbe modificare una variabile esistente, ma ha un errore di battitura, hai comunque un codice perfettamente legittimo che ha appena creato (e assegnato un valore a) una nuova variabile:

longVariableName = 1

// ...

longVaraibleName = longvariableName + anotherLongVariableName

Ora, osservando questo in isolamento, con il mio già menzionato un errore di battitura come fonte del problema, è probabilmente piuttosto facile trovare l'errore di battitura e il problema qui. In un programma lungo, in cui questo è sepolto in mezzo a un sacco di altri codici, è molto più facile mancare.

Anche attualmente con molte lingue digitate dinamicamente, puoi ancora ottenere lo stesso problema di base abbastanza facilmente. Alcuni hanno qualche possibilità di avvertirti se assegni a una variabile, ma non la leggi mai (il che euristicamente prende alcuni problemi come questo) entrambi gli altri non hanno cose del genere.

    
risposta data 21.03.2016 - 19:03
fonte
0

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

Esempio: - crei un programma che chiede all'utente di inserire qualsiasi numero, in questo caso devi 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 tenta di eseguire l'allocazione da solo, può causare un utilizzo inefficiente della memoria. D'altra parte, se si specifica il tipo di dati nel programma, dopo la compilazione la macchina alloca lo spazio appropriato in base alle esigenze.

    
risposta data 21.03.2016 - 19:41
fonte

Leggi altre domande sui tag