Por que você precisa especificar o tipo de dado ao declarar variáveis?

41

Na maioria das linguagens de codificação (se não todas), você precisa declarar variáveis. Por exemplo, em C # se for um campo numérico, então

int PhoneNumber

Se eu estiver usando o idioma inglês normal, não preciso declarar PhoneNumber as int para usá-lo. Por exemplo, se eu pedir ao meu amigo Sam para me dar o seu número de telefone eu digo:

"Sam give me the phonenumber"

Eu não diria

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

Por que precisamos especificar o tipo de dados?

    
por dick smith 21.03.2016 / 00:11
fonte

13 respostas

79

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

[…]

Why do we have to specify data type at all?

Essas são duas perguntas independentes:

  • Por que precisamos declarar variáveis?
  • Por que precisamos declarar tipos?

Aliás, a resposta para ambos é: nós não.

Existem muitas linguagens de programação estaticamente tipadas nas quais você não precisa declarar os tipos. O compilador pode inferir os tipos do contexto ao redor e o uso.

Por exemplo, no Scala você pode dizer

val age: Int = 23

ou você poderia apenas dizer

val age = 23

Os dois são exatamente equivalentes: o compilador irá inferir que o tipo é Int da expressão de inicialização 23 .

Da mesma forma, em C♯, você pode dizer qualquer um deles e ambos significam exatamente a mesma coisa:

int age = 23;
var age = 23;

Esse recurso é chamado inferência de tipo , e muitos idiomas além de Scala e C♯ possuem: Haskell, Kotlin, Ceilão, ML, F♯, C ++, o nome dele. Até mesmo o Java tem formas limitadas de inferência de tipos.

Em linguagens de programação dinamicamente tipadas, as variáveis nem possuem tipos. Tipos só existem dinamicamente em tempo de execução, não estaticamente. Somente valores e expressões possuem tipos e somente no tempo de execução, variáveis não possuem tipos.

Por exemplo no ECMAScript:

const age = 23;
let age = 23;

E por último, em muitos idiomas, você nem precisa declarar variáveis. por exemplo. em Ruby:

age = 23

Na verdade, esse último exemplo é válido em várias linguagens de programação. A mesma linha de código também funcionaria em Python, por exemplo.

Então,

  • mesmo em idiomas com tipagem estática em que as variáveis têm tipos, você não precisa necessariamente declará-las,
  • em linguagens dinamicamente tipadas, as variáveis não têm tipos, então obviamente você não pode sequer declará-las,
  • em vários idiomas, você nem precisa declarar variáveis
por 21.03.2016 / 01:52
fonte
52

Quando você usa linguagem natural para se referir à informação, ela não é muito precisa e, em particular, não comunica aos outros muito sobre sua intenção. Problemas semelhantes ocorrem quando se tenta fazer matemática em linguagem natural: simplesmente não é preciso o suficiente.

A programação é complexa; erros são muito fáceis de encontrar. Os tipos fazem parte de um sistema de verificações que são projetados para impedir estados de programas ilegais, detectando condições de erro. Diferentes idiomas usam os tipos de forma diferente: alguns idiomas usam intensamente os tipos para detectar erros no tempo de compilação. Quase todas as linguagens têm alguma noção de tipos incompatíveis como um erro de tempo de execução. Geralmente, um erro de tipo indica um bug de algum tipo no programa. Quando permitimos que os programas continuem apesar dos erros, provavelmente recebemos respostas muito ruins. Preferimos parar o programa em vez de obter respostas incorretas ou incorretas.

Em outras palavras, os tipos expressam restrições sobre o comportamento do programa. Restrições, quando aplicadas por algum mecanismo, fornecem garantias. Tais garantias limitam a quantidade de raciocínio necessária para pensar sobre o programa, simplificando assim a tarefa de ler e manter o programa para programadores. Sem tipos e sua implicação de ferramentas (ou seja, o compilador) que detectam erros de tipo, a carga de programação é consideravelmente maior e, portanto, mais cara.

É verdade que (muitos) humanos distinguem facilmente entre um número de telefone europeu, dos Estados Unidos e internacional. No entanto, o computador realmente não "pensa", e, se dito, discar um número de telefone dos estados unidos na europa, ou vice-versa. Tipos, por exemplo, são uma boa maneira de distinguir entre esses casos, sem ter que ensinar o computador a "pensar". Em alguns idiomas, podemos obter um erro de tempo de compilação para tentar misturar um número de telefone europeu em um sistema de telefonia americano. Esse erro nos diz que precisamos modificar nosso programa (talvez convertendo o número de telefone para uma seqüência de discagem internacional ou usando o número de telefone na Europa), antes mesmo de tentarmos executar o programa.

Além disso, como o computador não pensa, o nome do campo ou variável (por exemplo, phonenumber ) não significa nada para o computador. Para o computador, esse nome de campo / variável é apenas "blah123". Pense em como seu programa seria se todas as variáveis fossem "blahxxx". Yikes Bem, isso é o que o computador vê. Fornecer um tipo dá ao computador uma idéia do significado da variável que simplesmente não pode inferir apenas do seu nome.

Além disso, como diz @Robert, em muitas linguagens modernas, não precisamos especificar tipos tanto quanto antigamente, já que linguagens como C # executam "inferência de tipos", que é um conjunto de regras para determinar o tipo adequado para uma variável no contexto. C # fornece apenas inferência de tipos em variáveis locais, mas não em parâmetros formais, ou campos de classe ou instância.

    
por 21.03.2016 / 01:37
fonte
28

Além das outras respostas, há uma coisa que deve ser incluída. Lembre-se de que os computadores são apenas bits. Digamos que eu te dê os bytes:

26 3A 00 FF

O que isso significa ? É armazenado desta forma pelo computador, mas sem qualquer interpretação, é apenas bits . Pode ter 4 caracteres ascii. Pode ser um inteiro. Pode haver alguns bytes em uma matriz. Pode ser parte de um objeto. Pode ser um indicador de onde o vídeo do gato está em buffer. Quase todas as linguagens de programação do assembly precisam de alguma coisa para saber como interpretar os bits para fazê-los fazer uma computação significativa.

E como o computador não pode saber o significado desses bits, ele precisa ser informado - seja explicitamente via anotações de tipo ou implicitamente por meio de mecanismos de inferência de tipos mencionados nas outras respostas.

    
por 21.03.2016 / 03:32
fonte
22

A resposta para por que os computadores precisam dessas informações tem a ver com Representação de dados .

O nome do "tipo de dados" é uma referência a regras que ajudam o computador a armazenar e recuperar informações do estado bruto de 0s e 1s na memória do computador.

Por exemplo, seu caractere ASCII regular de 8 bits seria armazenado na memória do computador (RAM ou disco) como 01000001 (o caractere maiúsculo "A", código ASCII 65) ou 00001000 (o percentual sinal), ou qualquer combinação de 0's e 1s nesses 8 bits.

Por outro exemplo, um inteiro não assinado de 8 bits pode ser armazenado como 00000101 (o número 5) ou 00001000 (o número 8)

Observe como a representação binária de 8 e o caractere% podem ser os mesmos, mas eles significam coisas diferentes porque seus tipos são diferentes.

Mesmo as linguagens que inferem o tipo de dados, elas podem não ter a regra de que "todos os tipos de variáveis devem ser declarados pelo programador", eles têm regras como "se sua série de caracteres estiver entre aspas, é uma string "e muitas outras regras para cada tipo de dados.

Portanto, mesmo estes precisam de tipos de dados para entender o que significam os 0s e 1s, então eles podem, por exemplo, fazer a função de concatenação de strings se você tentar "adicionar" dois caracteres ou fazer integer se você estiver tentando adicione dois inteiros.

Em sua história também, digamos que você não pediu a Sam o número do telefone, mas Sam lhe dá um pedaço de papel que tem "1123581321" escrito nele. Você não podia ter certeza se Sam é apenas um fã dos primeiros oito números de Fibonacci, ou se é um número de telefone. Para adivinhar, você terá que levar em conta o contexto e as dicas disponíveis, como se você tivesse pedido a Sam um número de telefone há um dia ou a nota dissesse "Ligue para mim" ou se você contar os dígitos e encontrar corresponde aos padrões da maioria dos números de telefone. Só então você saberia que é um número de telefone para o qual você pode ligar e não alguns dígitos que você digitaria em uma calculadora.

Observe como essas dicas que o levaram a supor que o número era um número de telefone são semelhantes a como as dicas levam uma linguagem de computador que não exige declaração para deduzir o tipo de um valor.

    
por 21.03.2016 / 08:48
fonte
10

Em alguns idiomas, não é necessário especificar o tipo de dados.

As linguagens que suportam a inferência de tipos geralmente podem descobrir o tipo de dados do seu uso. Por exemplo,

var name = "Ali"

é internamente digitado como uma string, porque o valor é cercado por aspas.

Algumas linguagens não exigem que você declare a variável; a variável é criada quando é usada pela primeira vez. No entanto, é considerado uma prática recomendada declarar especificamente suas variáveis por várias razões importantes; principalmente porque isso melhor expressa sua intenção.

    
por 21.03.2016 / 00:23
fonte
9

Porque é isso que o design da linguagem especifica. Portanto, para responder à sua pergunta, precisamos examinar a intenção por trás da digitação explícita em linguagens como C # e C ++. (Bem, o C # faz isso porque o C ++ faz isso porque o C faz isso, então precisamos olhar para o caminho da intenção naquela época).

Primeiro, tipagem explícita e estática fornece rigor na codificação - especificar uma variável como sendo um inteiro significa que o compilador e o software devem ficar surpresos e lançar um erro quando você atribuir um caractere ou string à variável. Digitação dinâmica pode causar dores de cabeça para os desavisados (basta olhar para a abordagem PHP ou javascripts para a veracidade de coisas como matrizes e seqüências de caracteres vazias).

Você pode ter static com digitação implícita - inicializar uma variável como uma string significa que a variável deve ser apenas uma string, mas meu sentimento é que isso pode causar problemas para os humanos lerem o código (eu tendo a digitação dinâmica quando é digitação implícita).

Além disso, é possível, em alguns idiomas, escrever algo como esse pseudocódigo para inicializar uma classe a partir de uma entrada de string:

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

Em segundo lugar, a digitação explícita também anda de mãos dadas com a alocação de memória. Um int é sempre com muitos bytes. Um número de telefone tem tantos bytes. O compilador pode atribuir um bloco de memória de tamanho apropriado que pode ser usado posteriormente sem ter que ver quanto espaço ele precisará ao atribuir um valor.

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

Finalmente, isso elimina a confusão ... é 123 um inteiro ou um inteiro não assinado? Eles precisam do mesmo número de bytes, mas o valor máximo armazenado em variáveis de qualquer tipo é muito diferente ...

Isso não quer dizer que explícito é melhor do que implícito - mas o design da linguagem depende desses tipos de escolhas, e o C # funcionaria de maneira diferente com a digitação implícita. PHP e javascript funcionariam de maneira diferente com digitação explícita.

    
por 21.03.2016 / 01:32
fonte
5

Porque Sam é mais inteligente que compiladores. Por exemplo, quando você diz o número de telefone, não especifica se deseja o prefixo do país ou o código de área, seja o número do trabalho, onde apenas os últimos 4 dígitos são necessários. Além disso, se você pedir o número da pizzaria local, você seria capaz de lidar com a resposta "pizza4u".

Sam, descobre isso do contexto. Enquanto o compilador também pode descobrir a partir do contexto, Sam será melhor nisso (e é capaz de interromper o processo para pedir esclarecimentos).

Existem duas abordagens básicas para tipos e variáveis, ou a variável tem um tipo, em cujo caso ações que não são permitidas pelo tipo são proibidas e impedem a compilação, ou o valor tem um tipo e ações que não são permitido pelo tipo são capturados em tempo de execução.

Cada abordagem tem suas vantagens e desvantagens. Em geral, os criadores de compiladores tentam minimizar as desvantagens e maximizar as vantagens. É por isso que o C #, por exemplo, permite var phoneNumber = GetPhoneNumber(); e deduzirá o tipo de phoneNumber da assinatura de GetPhoneNumber. Isso significa que você precisa declarar o tipo para o método, mas não a variável que recebe o resultado. Por outro lado, existem vários projetos de dica / reforço de tipo para javascript. Tudo é uma troca.

    
por 21.03.2016 / 04:06
fonte
3

É uma questão de como os dados são armazenados. Sua interação com Sam faria uma comparação melhor se você pedisse para que pudesse escrevê-la, mas tivesse apenas oito caracteres de papel.

"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!"

Então, em vez disso, a maioria dos idiomas faz você declarar um tipo, para que ele saiba e se prepare antes:

"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!"

Fica ainda mais difícil quando você olha para as formas fundamentais em que os dados são armazenados. Se você é como eu, você tem um caderno com notas diversas, números rabiscados, sem contexto ou rotulação para qualquer coisa, e você não tem idéia do que isso significa três dias depois. Este é um problema para os computadores muitas vezes também. Muitas linguagens têm os tipos "int" (int, long, short, byte) e "float" (float, double). Por que isso é necessário?

Bem, primeiro vamos ver como um inteiro é armazenado e geralmente representado dentro do computador. Você provavelmente está ciente de que, no nível básico, é tudo binário (1's e 0's). Binário é na verdade um sistema numérico que funciona exatamente como o nosso sistema numérico decimal. Em decimal, você conta de 0 a 9 (com zeros iniciais infinitos implícitos que você não escreve), então você rola de volta para 0 e incrementa o próximo dígito para que você tenha 10. Você repete até você rolar de 19 para 20, repita até passar de 99 para 100 e assim por diante.

Binário não é diferente, exceto que em vez de 0 a 9, você conta 0 a 1. 0, 1, 10, 11, 100, 101, 110, 111, 1000. Então, quando você digita 9, na memória, gravado em binário como 1001. Este é um número real. Pode ser adicionado, subtraído, multiplicado, etc., exatamente dessa forma. 10 + 1 = 11. 10 + 10 = 100 (role sobre 1 para 0 e carregue o 1). 11 x 10 = 110 (e equivalentemente, 11 + 11 = 110).

Agora, na memória real (registradores incluídos), há uma lista, array, o que você quiser chamá-lo, de bits (potencial 1 ou 0 ') próximos uns dos outros, que é como ele mantém esses bits logicamente organizados para fazer um número maior que 1. Problema é, o que você faz com decimais? Você não pode simplesmente inserir uma peça de hardware entre os dois bits no registrador, e custaria demais acrescentar "bits decimais" entre cada par de bits. Então o que fazer?

Você codifica. Geralmente, a arquitetura da CPU ou do software determinará como isso é feito, mas uma maneira comum é armazenar um sinal (+ ou -, geralmente 1 é negativo) no primeiro bit do registro, uma mantissa (o seu número mudou, no entanto, muitas vezes é necessário para se livrar do decimal) para o seguinte número X de bits e um expoente (o número de vezes que você teve que mudá-lo) para o restante. É semelhante à notação científica.

A digitação permite que o compilador saiba o que está vendo. Imagine que você armazenou o valor 1.3 no registrador 1. Vamos criar nosso próprio esquema de codificação, 1 bit para sinal, 4 para mantissa, 3 para expoente (1 bit para sinal, 2 para magnitude). Este é um número positivo, então o sinal é positivo (0). Nossa mantissa seria 13 (1101) e nosso expoente seria -1 (101 (1 para negativo, 01 = 1)). Então nós armazenamos 01101101 no registrador 1. Agora nós não digitamos essa variável, então quando o tempo de execução vai usá-la, ela diz "certo, isso é um inteiro porque não" então quando ele imprime o valor vemos 109 (64 + 32 + 8 + 4 + 1), o que obviamente não está certo.

Nem todo idioma exige que você digite explicitamente, no entanto. C # tem uma palavra-chave "var" que faz com que o tipo de uma variável seja interpretada em tempo de compilação, e outras linguagens como Javascript são totalmente dinamicamente digitadas, a ponto de você poder armazenar um inteiro em uma variável e então atribuí-lo a um booleano. atribuí-lo novamente a uma string e o idioma mantém o controle de tudo.

Mas é muito mais fácil no compilador, intérprete ou tempo de execução - e geralmente resulta em um programa mais rápido, já que ele não precisa gastar recursos valiosos ordenando tudo - para perguntar a você, o programador, que tipo de dados você está dando.

    
por 21.03.2016 / 18:24
fonte
2

Existem linguagens de programação onde você não tem que declarar tipos de dados para suas variáveis. Existem até mesmo linguagens de programação nas quais você não precisa declarar variáveis antes; você pode apenas usar , imediatamente.

O problema de não declarar nomes de variáveis é que, se acidentalmente digitar errado o nome de uma variável, você criou acidentalmente uma nova variável completamente não relacionada. Então, quando você executa seu programa, você não consegue descobrir porque o inferno essa variável que você configurou de repente não tem nada ... Até que, depois de muitas horas de depuração, você percebe que digitou o maldito nome errado! GRRR !!

Então eles fizeram isso para que você declare os nomes das variáveis que você usará antes. E agora, quando você digita um nome errado, você obtém um erro em tempo de compilação, que imediatamente diz a você exatamente onde está o erro, antes que seu programa seja executado. Isso não é muito mais fácil?

Mesma transação com tipos de dados. Existem linguagens de programação onde você não tem que declarar o tipo de coisa que deveria ser. Se você tem uma variável customer , que na verdade é apenas o nome de um cliente, não o objeto inteiro do cliente, tentar buscar o endereço do cliente de uma string comum simples ... não vai funcionar. Todo o ponto da tipagem estática é que o programa não compilará; reclamará em voz alta, apontando para o lugar exato onde está o problema. Isso é muito mais rápido do que executar seu código e tentar descobrir por que diabos não está funcionando.

Todos esses são recursos para dizer ao compilador o que você pretendia fazer, para que ele possa verificar o que você realmente fez e ter certeza de que faz sentido. Isso torna possível para o compilador automaticamente localizar bugs para você, o que é um grande negócio.

(Longe do passado distante, você não tinha que declarar sub-rotinas . Você apenas GOSUB para um número de linha em particular. Se você quisesse passar informações entre sub-rotinas, você definir determinadas variáveis globais, chamar sua sub-rotina e, em seguida, inspecionar outras variáveis quando a sub-rotina retorna.Mas isso torna assustadoramente fácil esquecer de inicializar um dos parâmetros.Então agora quase todos     

por 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?

Vá até MathOverflow ou Ciência da computação teórica e leia por um tempo para ter uma idéia de como os humanos se comunicavam uns com os outros quando queriam assegurar que não houvesse possibilidade de mal-entendido. Ou leia o padrão para alguma linguagem de programação madura.

Você descobrirá que definir quais tipos de valores são permitidos para um termo é parte da prática de comunicação realmente precisa, mesmo de humano para humano.

O que você notou é que as interações do dia-a-dia são bastante regulares e as humanas são bem tolerantes a falhas, portanto, um equívoco sobre os números de telefone geralmente é evitado pelo conhecimento compartilhado dos participantes.

Mas você já tentou derrubar um número de telefone de alguém em outro país? Eles lhe disseram explicitamente quantas vezes apertar zero para chegar ao endereçamento internacional? Eles te contaram o código do país deles? Você reconheceu isso? Quantos dígitos você esperava? Quantos você conseguiu? Você sabia como agrupar os dígitos? Ou mesmo se o agrupamento tem significância?

De repente, o problema é muito mais difícil e você provavelmente teve muito mais cuidado para verificar explicitamente que o número recebido foi compreendido da maneira que o remetente quis dizer.

    
por 22.03.2016 / 06:47
fonte
0

Outro motivo para declarar tipos é a eficiência. Enquanto um inteiro pode ser armazenado em 1 byte, ou 2 bytes, ou 4, um programa usando um número muito grande de variáveis pode usar 4 vezes a memória necessária, dependendo do que está sendo feito. Apenas o programador sabe se um espaço de armazenamento menor é viável, então ele pode dizer isso declarando o tipo.

Além disso, objetos dinamicamente tipificados permitem vários tipos possíveis, em tempo real. Isso poderia incorrer em alguma sobrecarga "sob o capô", desacelerando o programa em comparação a ficar com um tipo o tempo todo.

    
por 21.03.2016 / 18:55
fonte
0

Várias linguagens de programação antigas (especialmente Fortran) não exigiam que você declarasse variáveis antes de usar.

Isso levou a vários problemas. Um realmente óbvio é que o compilador não consegue mais capturar erros tipográficos de maneira quase tão confiável. Se você tem código que deveria modificar uma variável existente, mas tem um erro de digitação, você ainda tem um código perfeitamente legítimo que acabou de criar (e atribuiu um valor a) uma nova variável:

longVariableName = 1

// ...

longVaraibleName = longvariableName + anotherLongVariableName

Agora, olhando para isto isoladamente, com o meu já tendo mencionado um erro de digitação como a fonte do problema, é provavelmente muito fácil encontrar o erro e o problema aqui. Em um programa longo, onde isso é enterrado no meio de muitos outros códigos, é muito mais fácil perder.

Mesmo atualmente com muitos idiomas dinamicamente tipados, você ainda pode obter o mesmo problema básico facilmente. Alguns têm alguma facilidade para avisá-lo se você atribuir a uma variável, mas nunca a lê (que heuristicamente pega alguns problemas como este), ambos os outros não têm tais coisas.

    
por 21.03.2016 / 19:03
fonte
0

Quando você declara alguma variável, algum espaço é alocado na memória, mas a máquina (neste caso, computador) ainda não sabe que espaço deve ser alocado para aquela variável.

Exemplo: - você cria um programa que pede ao usuário para inserir qualquer número, neste caso você tem que especificar um tipo de dados para armazenar esse número, caso contrário a máquina não pode julgar por si própria que deve alocar 2 bytes ou 2 gigabytes , se ele tentar fazer alocação sozinho, isso pode resultar em uso ineficiente da memória. Por outro lado, se você especificar o tipo de dados em seu programa, então, após a compilação, a máquina alocaria o espaço adequado de acordo com a necessidade.

    
por 21.03.2016 / 19:41
fonte