Tipo de dados - Data type

A hierarquia de tipo padrão do Python 3

Em ciência da computação e programação de computadores , um tipo de dados ou simplesmente tipo é um atributo de dados que diz ao compilador ou intérprete como o programador pretende usar os dados. A maioria das linguagens de programação oferece suporte a tipos de dados básicos de números inteiros (de tamanhos variados), números de ponto flutuante (que se aproximam dos números reais), caracteres e booleanos . Um tipo de dados restringe os valores que uma expressão , como uma variável ou uma função, pode assumir. Este tipo de dados define as operações que podem ser feitas nos dados, o significado dos dados e a maneira como os valores desse tipo podem ser armazenados. Um tipo de dados fornece um conjunto de valores dos quais uma expressão (isto é, variável, função, etc.) pode receber seus valores.

Conceito

Os tipos de dados são usados ​​em sistemas de tipos, que oferecem várias maneiras de definir, implementar e usá-los. Sistemas de tipos diferentes garantem graus variados de segurança de tipo .

Quase todas as linguagens de programação incluem explicitamente a noção de tipo de dados, embora linguagens diferentes possam usar terminologias diferentes.

Os tipos de dados comuns incluem:

Por exemplo, na linguagem de programação Java , o tipo int representa o conjunto de inteiros de 32 bits que variam em valor de −2.147.483.648 a 2.147.483.647, bem como as operações que podem ser realizadas em inteiros, como adição, subtração e multiplicação. Uma cor, por outro lado, pode ser representada por três bytes denotando as quantidades de vermelho, verde e azul, e uma string representando o nome da cor.

A maioria das linguagens de programação também permite que o programador defina tipos de dados adicionais, geralmente combinando vários elementos de outros tipos e definindo as operações válidas do novo tipo de dados. Por exemplo, um programador pode criar um novo tipo de dados denominado " número complexo " que incluiria partes reais e imaginárias. Um tipo de dados também representa uma restrição colocada sobre a interpretação de dados em um sistema de tipo , descrevendo a representação, interpretação e estrutura de valores ou objetos armazenados na memória do computador. O sistema de tipo usa informações de tipo de dados para verificar a exatidão dos programas de computador que acessam ou manipulam os dados.

A maioria dos tipos de dados em estatísticas têm tipos comparáveis ​​em programação de computador e vice-versa, conforme mostrado na tabela a seguir:

Estatisticas Programação
valor real ( escala de intervalo ) ponto flutuante
valor real ( escala de razão )
dados de contagem (geralmente não negativos) inteiro
dados binários boleano
Dados categóricos tipo enumerado
vetor aleatório lista ou matriz
matriz aleatória matriz bidimensional
árvore aleatória árvore

Definição

( Parnas, Shore & Weiss 1976 ) identificou cinco definições de um "tipo" que foram usadas - às vezes implicitamente - na literatura. Tipos, incluindo comportamento, se alinham mais de perto com modelos orientados a objetos , enquanto um modelo de programação estruturado tende a não incluir código e são chamados de estruturas de dados simples e antigas .

Os cinco tipos são:

Sintático
Um tipo é um rótulo puramente sintático associado a uma variável quando ela é declarada. Essas definições de "tipo" não dão nenhum significado semântico aos tipos.
Representação
Um tipo é definido em termos de sua composição de tipos mais primitivos - geralmente tipos de máquina.
Representação e comportamento
Um tipo é definido como sua representação e um conjunto de operadores manipulando essas representações.
Espaço de valor
Um tipo é um conjunto de valores possíveis que uma variável pode possuir. Tais definições permitem falar em uniões ( disjuntas ) ou produtos cartesianos de tipos.
Valorize o espaço e o comportamento
Um tipo é um conjunto de valores que uma variável pode possuir e um conjunto de funções que podem ser aplicadas a esses valores.

A definição em termos de representação era frequentemente feita em linguagens imperativas como ALGOL e Pascal , enquanto a definição em termos de espaço de valor e comportamento era usada em linguagens de nível superior, como Simula e CLU .

Classes de tipos de dados

Tipos de dados primitivos

Tipos de dados primitivos são tipicamente tipos que são internos ou básicos para uma implementação de linguagem.

Tipos de dados de máquina

Todos os dados em computadores baseados em eletrônica digital são representados como bits (alternativas 0 e 1) no nível mais baixo. A menor unidade de dados endereçável é geralmente um grupo de bits chamado byte (geralmente um octeto , que tem 8 bits). A unidade processada por instruções de código de máquina é chamada de palavra (a partir de 2011, normalmente 32 ou 64 bits). A maioria das instruções interpreta a palavra como um número binário , de forma que uma palavra de 32 bits pode representar valores inteiros sem sinal de 0 a ou valores inteiros com sinal de a . Por causa do complemento de dois , a linguagem de máquina e a máquina não precisam distinguir entre esses tipos de dados não assinados e assinados em sua maior parte.

Os números de ponto flutuante usados ​​para aritmética de ponto flutuante usam uma interpretação diferente dos bits em uma palavra. Consulte aritmética de ponto flutuante para obter detalhes.

Os tipos de dados de máquina precisam ser expostos ou disponibilizados em sistemas ou linguagens de programação de baixo nível , permitindo um controle refinado sobre o hardware. A linguagem de programação C , por exemplo, fornece tipos inteiros de várias larguras, como shorte long. Se um tipo nativo correspondente não existir na plataforma de destino, o compilador os dividirá em código usando os tipos existentes. Por exemplo, se um inteiro de 32 bits for solicitado em uma plataforma de 16 bits, o compilador irá tratá-lo tacitamente como uma matriz de dois inteiros de 16 bits.

Na programação de nível superior, os tipos de dados de máquina costumam ser ocultos ou abstraídos como um detalhe de implementação que tornaria o código menos portátil se exposto. Por exemplo, um numerictipo genérico pode ser fornecido em vez de inteiros de alguma largura de bit específica.

Tipo booleano

O tipo booleano representa os valores verdadeiro e falso . Embora apenas dois valores sejam possíveis, eles raramente são implementados como um único dígito binário por razões de eficiência. Muitas linguagens de programação não têm um tipo booleano explícito, interpretando (por exemplo) 0 como falso e outros valores como verdadeiros. Os dados booleanos referem-se à estrutura lógica de como a linguagem é interpretada para a linguagem de máquina. Nesse caso, um Booleano 0 se refere à lógica False. True é sempre diferente de zero, especialmente aquele que é conhecido como Boolean 1.

Enumerações

O tipo enumerado possui valores distintos, que podem ser comparados e atribuídos, mas que não possuem necessariamente qualquer representação concreta particular na memória do computador; compiladores e interpretadores podem representá-los arbitrariamente. Por exemplo, os quatro naipes em um baralho de cartas podem ser quatro enumeradores chamados CLUBE , DIAMANTE , CORAÇÃO , ESPADA , pertencentes a um tipo enumerado chamado naipe . Se uma variável V é declarada tendo suit como seu tipo de dados, pode-se atribuir qualquer um desses quatro valores a ela. Algumas implementações permitem que os programadores atribuam valores inteiros aos valores de enumeração ou mesmo os tratem como equivalentes de tipo a inteiros.

Tipos numéricos

Tal como:

  • Os tipos de dados inteiros ou "números não fracionários". Pode ser subdigitado de acordo com sua capacidade de conter valores negativos (por exemplo, unsignedem C e C ++). Também pode ter um pequeno número de subtipos predefinidos (como shorte longem C / C ++); ou permitir que os usuários definam livremente subintervalos como 1..12 (por exemplo, Pascal / Ada ).
  • Os tipos de dados de ponto flutuante geralmente representam valores como valores fracionários de alta precisão ( números racionais , matematicamente), mas às vezes são chamados erroneamente de reais (evocativos de números reais matemáticos ). Eles geralmente têm limites predefinidos em seus valores máximos e em sua precisão. Normalmente armazenado internamente na forma a × 2 b (onde a e b são inteiros), mas exibido na forma decimal familiar .
  • Os tipos de dados de ponto fixo são convenientes para representar valores monetários. Eles geralmente são implementados internamente como inteiros, levando a limites predefinidos.
  • Os tipos numéricos Bignum ou de precisão arbitrária não têm limites predefinidos. Eles não são tipos primitivos e são usados ​​com moderação por razões de eficiência.

Tipos compostos

Os tipos compostos são derivados de mais de um tipo primitivo. Isso pode ser feito de várias maneiras. As formas como são combinadas são chamadas de estruturas de dados . A composição de um tipo primitivo em um tipo composto geralmente resulta em um novo tipo, por exemplo, array-of-integer é um tipo diferente de inteiro .

  • Uma matriz (também chamada de vetor, lista ou sequência) armazena vários elementos e fornece acesso aleatório a elementos individuais. Os elementos de uma matriz normalmente (mas não em todos os contextos) devem ser do mesmo tipo. As matrizes podem ser de comprimento fixo ou expansível. Índices em uma matriz normalmente precisam ser inteiros (caso contrário, pode-se enfatizar esse relaxamento falando sobre uma matriz associativa ) de um intervalo específico (se nem todos os índices nesse intervalo corresponderem a elementos, pode ser uma matriz esparsa ).
  • Registro (também chamado de tupla ou estrutura) Os registros estão entre as estruturas de dados mais simples . Um registro é um valor que contém outros valores, normalmente em número e sequência fixos e geralmente indexados por nomes. Os elementos dos registros geralmente são chamados de campos ou membros .
  • União . Uma definição de tipo de união irá especificar quais dos vários tipos primitivos permitidos podem ser armazenados em suas instâncias, por exemplo, "float ou inteiro longo". Compare com um registro , que pode ser definido para conter um float e um inteiro; ao passo que, em um sindicato, há apenas um tipo permitido por vez.
    • Uma união marcada (também chamada de variante , registro de variante, união discriminada ou união disjunta) contém um campo adicional que indica seu tipo atual para segurança de tipo aprimorada.
  • Um conjunto é uma estrutura de dados abstrata que pode armazenar certos valores, sem qualquer ordem particular e sem valores repetidos. Os valores em si não são recuperados de conjuntos, em vez disso, um valor testa a associação para obter um booleano "in" ou "not in".
  • Um objeto contém vários campos de dados, como um registro, e também várias sub-rotinas para acessá-los ou modificá-los, chamados métodos .

Muitos outros são possíveis, mas tendem a ser outras variações e compostos dos itens acima. Por exemplo, uma lista encadeada pode armazenar os mesmos dados que um array, mas fornece acesso sequencial em vez de aleatório e é constituída de registros na memória dinâmica ; embora indiscutivelmente uma estrutura de dados em vez de um tipo em si , também é comum e distinto o suficiente para justificar sua inclusão em uma discussão de tipos compostos.

Tipos de string e texto

Tal como:

  • Um caractere , que pode ser uma letra de algum alfabeto , um dígito, um espaço em branco, um sinal de pontuação, etc.
  • Uma string , que é uma sequência de caracteres. Strings são normalmente usados ​​para representar palavras e texto, embora o texto em todos os casos, exceto os mais triviais, envolva muito mais do que uma sequência de caracteres.

Os tipos de caracteres e strings podem armazenar sequências de caracteres de um conjunto de caracteres como ASCII . Como a maioria dos conjuntos de caracteres inclui os dígitos , é possível ter uma string numérica, como "1234". No entanto, muitos idiomas os tratam como pertencentes a um tipo diferente do valor numérico 1234.

Os tipos de caracteres e strings podem ter subtipos diferentes de acordo com a "largura" do caractere necessária. O ASCII original de 7 bits foi considerado limitado e substituído por conjuntos de 8 e 16 bits, que podem codificar uma ampla variedade de alfabetos não latinos (como hebraico e chinês ) e outros símbolos. Strings podem ser extensíveis para caber ou de tamanho fixo, mesmo na mesma linguagem de programação. Eles também podem ser subtipados por seu tamanho máximo.

Nota: Strings não são um tipo de dados primitivo em todas as linguagens. Em C , por exemplo, eles são compostos de uma série de caracteres.

Tipos de dados abstratos

Qualquer tipo de dados que não especifica a representação concreta dos dados é um tipo de dados abstrato . Em vez disso, uma especificação formal baseada nas operações do tipo de dados é usada para descrevê-lo. Qualquer implementação de uma especificação deve cumprir as regras fornecidas. Tipos de dados abstratos são usados ​​em semântica formal e verificação de programa e, menos estritamente, em design .

Além da verificação, uma especificação pode ser imediatamente transformada em uma implementação. A família OBJ de linguagens de programação, por exemplo, baseia-se nesta opção usando equações para especificação e reescrita para executá-las. A especificação algébrica era um assunto importante de pesquisa em Ciência da Computação por volta de 1980 e quase um sinônimo para tipos de dados abstratos naquela época. Ele tem uma base matemática em álgebra universal . A linguagem de especificação pode ser mais expressiva, permitindo outras fórmulas do que apenas equações.

Um exemplo típico é a hierarquia dos tipos de dados de lista , saco e conjunto . Todos esses tipos de dados podem ser declarados por três operações: null , que constrói o contêiner vazio, único , que constrói um contêiner a partir de um único elemento e append , que combina dois contêineres do mesmo tipo. A especificação completa para os três tipos de dados pode ser fornecida pelas seguintes regras sobre essas operações:

- null é o neutro esquerdo e direito: anexar (nulo, A) = A, anexar (A, nulo) = A.
- para uma lista, append é associativo: anexar (anexar (A, B), C) = anexar (A, anexar (B, C)).
- bolsas adicionam comutatividade: anexar (B, A) = anexar (A, B).
- finalmente, um conjunto também é idempotente: anexar (A, A) = A.

O acesso aos dados pode ser especificado provavelmente, por exemplo, uma função de membro para esses contêineres por:

- membro (X, único (Y)) = eq (X, Y)
- membro (X, nulo) = falso
- membro (X, anexar (A, B)) = ou (membro (X, A), membro (X, B))

Outros tipos

Os tipos podem ser baseados ou derivados dos tipos básicos explicados acima. Em algumas linguagens, como C, as funções têm um tipo derivado do tipo de seu valor de retorno .

Ponteiros e referências

O principal tipo derivado não composto é o ponteiro , um tipo de dados cujo valor se refere diretamente a (ou "aponta para") outro valor armazenado em outro lugar na memória do computador usando seu endereço . É um tipo primitivo de referência . (Em termos cotidianos, o número de uma página de um livro pode ser considerado um dado que se refere a outro). Os ponteiros geralmente são armazenados em um formato semelhante a um número inteiro; entretanto, a tentativa de cancelar a referência ou "procurar" um ponteiro cujo valor nunca foi um endereço de memória válido faria com que o programa travasse. Para amenizar esse problema potencial, os ponteiros são considerados um tipo separado para o tipo de dados para o qual eles apontam, mesmo se a representação subjacente for a mesma.

Tipos de função

Embora funções também possam ser atribuídas a um tipo, seu tipo não é considerado um tipo de dados na configuração deste artigo. Aqui, os dados são vistos como distintos dos algoritmos . Na programação, as funções estão fortemente relacionadas com o último. Mas, como um princípio central do processamento universal de dados é que os algoritmos podem ser representados como dados , por exemplo, descrição textual e programas binários, o contraste entre dados e funções tem limites. Na verdade, não apenas as funções podem ser representadas por dados, mas as funções também podem ser usadas para codificar dados . Muitos sistemas de tipos contemporâneos se concentram fortemente em tipos de funções e muitas linguagens modernas permitem que as funções operem como cidadãos de primeira classe .

Excluir funções de serem tratadas como tipos de dados não é incomum em campos relacionados. A lógica de predicado, por exemplo, não permite a aplicação de quantificadores em nomes de função ou predicado.

Metatipos

Algumas linguagens de programação representam as informações de tipo como dados, permitindo a introspecção e reflexão de tipo . Em contraste, os sistemas de tipo de ordem superior , embora permitam que os tipos sejam construídos a partir de outros tipos e passados ​​para funções como valores, normalmente evitam basear decisões computacionais neles.

Tipos de utilidades

Por conveniência, as linguagens de alto nível podem fornecer tipos de dados do "mundo real" já prontos, por exemplo , horas , datas , valores monetários e memória , mesmo quando a linguagem permitir que eles sejam construídos a partir de tipos primitivos.

Sistemas de tipo

Um sistema de tipos associa tipos a valores calculados. Examinando o fluxo desses valores, um sistema de tipos tenta provar que nenhum erro de tipo pode ocorrer. O sistema de tipos em questão determina o que constitui um erro de tipo, mas um sistema de tipos geralmente procura garantir que as operações que esperam um certo tipo de valor não sejam usadas com valores para os quais essa operação não faz sentido.

Um compilador pode usar o tipo estático de um valor para otimizar o armazenamento de que precisa e a escolha de algoritmos para operações no valor. Em muitos compiladores C, o tipo de dados, por exemplo, é representado em 32 bits , de acordo com a especificação IEEE para números de ponto flutuante de precisão simples . Assim, eles usarão operações de microprocessador específicas de ponto flutuante nesses valores (adição, multiplicação de ponto flutuante, etc.). float

A profundidade das restrições de tipo e a maneira de sua avaliação afetam a digitação do idioma. Uma linguagem de programação pode ainda associar uma operação com algoritmos concretos variáveis ​​em cada tipo no caso de polimorfismo de tipo . A teoria dos tipos é o estudo dos sistemas de tipos, embora os sistemas de tipos concretos das linguagens de programação se originem de questões práticas de arquitetura de computador, implementação de compilador e design de linguagem.

Os sistemas de tipos podem ser estáticos ou dinâmicos , de tipagem forte ou fraca e assim por diante.

Veja também

Referências

Leitura adicional

links externos