Registro (ciência da computação) - Record (computer science)

Na ciência da computação , um registro (também chamado de estrutura , estrutura ou dados compostos ) é uma estrutura de dados básica . Os registros em um banco de dados ou planilha são geralmente chamados de " linhas ".

Um registro é uma coleção de campos , possivelmente de diferentes tipos de dados, normalmente em um número e sequência fixos. Os campos de um registro também podem ser chamados de membros , particularmente na programação orientada a objetos ; os campos também podem ser chamados de elementos , embora isso possa causar confusão com os elementos de uma coleção .

Por exemplo, uma data pode ser armazenada como um registro contendo um campo numérico de ano , um campo de mês representado como uma string e um campo numérico de dia do mês . Um registro pessoal pode conter um nome , um salário e uma classificação . Uma ficha círculo pode conter um centro e um raio -neste caso, o próprio centro pode ser representada como um ponto de ficha contendo x e y coordenadas.

Os registros se distinguem das matrizes pelo fato de que seu número de campos é geralmente fixo, cada campo tem um nome e cada campo pode ter um tipo diferente.

Um tipo de registro é um tipo de dados que descreve esses valores e variáveis. A maioria das linguagens de computador modernas permite ao programador definir novos tipos de registro. A definição inclui a especificação do tipo de dados de cada campo e um identificador (nome ou rótulo) pelo qual ele pode ser acessado. Na teoria dos tipos , os tipos de produtos (sem nomes de campo) são geralmente preferidos devido à sua simplicidade, mas os tipos de registro apropriados são estudados em linguagens como System F-sub . Como os registros teóricos de tipo podem conter campos tipificados por função de primeira classe, além de dados, eles podem expressar muitos recursos da programação orientada a objetos .

Os registros podem existir em qualquer meio de armazenamento, incluindo memória principal e dispositivos de armazenamento em massa , como fitas magnéticas ou discos rígidos . Os registros são um componente fundamental da maioria das estruturas de dados, especialmente estruturas de dados vinculadas . Muitos arquivos de computador são organizados como matrizes de registros lógicos , geralmente agrupados em registros físicos maiores ou blocos para maior eficiência.

Os parâmetros de uma função ou procedimento geralmente podem ser vistos como os campos de uma variável de registro; e os argumentos passados ​​para essa função podem ser vistos como um valor de registro que é atribuído a essa variável no momento da chamada. Além disso, na pilha de chamadas frequentemente usada para implementar chamadas de procedimento, cada entrada é um registro de ativação ou quadro de chamada , contendo os parâmetros de procedimento e variáveis ​​locais, o endereço de retorno e outros campos internos.

Um objeto em linguagem orientada a objetos é essencialmente um registro que contém procedimentos especializados para lidar com aquele registro; e os tipos de objeto são uma elaboração de tipos de registro. De fato, na maioria das linguagens orientadas a objetos, os registros são apenas casos especiais de objetos e são conhecidos como estruturas de dados antigas simples (PODSs), para contrastar com objetos que usam recursos OO.

Um registro pode ser visto como o análogo de computador de uma tupla matemática , embora uma tupla possa ou não ser considerada um registro e vice-versa, dependendo das convenções e da linguagem de programação específica. Na mesma linha, um tipo de registro pode ser visto como a linguagem de computador análogo ao produto cartesiano de dois ou mais conjuntos matemáticos , ou a implementação de um tipo de produto abstrato em uma linguagem específica.

Chaves

Um registro pode ter zero ou mais chaves . Uma chave é um campo ou conjunto de campos no registro que serve como um identificador. Uma chave exclusiva é geralmente chamada de chave primária ou simplesmente a chave de registro . Por exemplo, um arquivo de funcionário pode conter o número do funcionário, nome, departamento e salário. O número do funcionário será único na organização e será a chave primária. Dependendo do meio de armazenamento e da organização do arquivo, o número do funcionário pode ser indexado - que também é armazenado em um arquivo separado para tornar a pesquisa mais rápida. O código do departamento pode não ser exclusivo; ela também pode ser indexada, caso em que seria considerada uma chave secundária ou chave alternativa . Se não for indexado, todo o arquivo do funcionário terá que ser verificado para produzir uma lista de todos os funcionários de um departamento específico. O campo salário normalmente não seria considerado utilizável como uma chave. A indexação é um fator considerado ao projetar um arquivo.

História

Folha de diário do Censo dos Estados Unidos de 1880 , mostrando dados tabulares com linhas de dados, cada um sendo um registro correspondente a uma única pessoa.

O conceito de um registro pode ser rastreado em vários tipos de tabelas e livros usados ​​na contabilidade desde tempos remotos. A noção moderna de registros na ciência da computação, com campos de tipo e tamanho bem definidos, já estava implícita nas calculadoras mecânicas do século 19, como a Máquina Analítica de Babbage .

Cartão perfurado Hollerith (1895)

O meio legível por máquina original usado para dados (em oposição ao controle) era o cartão perfurado usado para registros no Censo dos Estados Unidos de 1890 : cada cartão perfurado era um único registro. Compare a entrada do diário de 1880 e o cartão perfurado de 1895. Os registros eram bem estabelecidos na primeira metade do século 20, quando a maior parte do processamento de dados era feita com cartões perfurados. Normalmente, cada registro de um arquivo de dados seria gravado em um cartão perfurado, com colunas específicas atribuídas a campos específicos. Geralmente, um registro era a menor unidade que podia ser lida do armazenamento externo (por exemplo, leitor de cartão, fita ou disco).

A maioria das implementações de linguagem de máquina e das primeiras linguagens de montagem não tinha sintaxe especial para registros, mas o conceito estava disponível (e amplamente utilizado) por meio do uso de registradores de índice , endereçamento indireto e código de automodificação . Alguns primeiros computadores, como o IBM 1620 , tinham suporte de hardware para delimitar registros e campos e instruções especiais para copiar esses registros.

O conceito de registros e campos era central em alguns utilitários de classificação e tabulação de arquivos iniciais , como o Report Program Generator (RPG) da IBM .

COBOL foi a primeira linguagem de programação difundida a oferecer suporte a tipos de registro, e seus recursos de definição de registro eram bastante sofisticados na época. A linguagem permite a definição de registros aninhados com campos alfanuméricos, inteiros e fracionários de tamanho e precisão arbitrários, bem como campos que formatam automaticamente qualquer valor atribuído a eles (por exemplo, inserção de sinais de moeda, pontos decimais e separadores de grupos de dígitos ) Cada arquivo está associado a uma variável de registro onde os dados são lidos ou gravados. COBOL também fornece umaMOVE CORRESPONDINGinstrução que atribui campos correspondentes de dois registros de acordo com seus nomes.

As primeiras linguagens desenvolvidas para computação numérica, como FORTRAN (até FORTRAN IV ) e Algol 60 , não tinham suporte para tipos de registro; mas versões posteriores dessas linguagens, como FORTRAN 77 e Algol 68 , os adicionaram. A linguagem de programação Lisp original também carecia de registros (exceto para a célula cons embutida ), mas suas expressões S forneceram um substituto adequado. A linguagem de programação Pascal foi uma das primeiras linguagens a integrar totalmente os tipos de registro com outros tipos básicos em um sistema de tipos logicamente consistente. A linguagem de programação PL / I fornecida para registros no estilo COBOL. A linguagem de programação C inicialmente forneceu o conceito de registro como um tipo de modelo ( struct) que poderia ser colocado em cima de uma área de memória, em vez de um tipo de dados de registro verdadeiro. Os últimos foram fornecidos eventualmente (pela typedefdeclaração), mas os dois conceitos ainda são distintos na linguagem. A maioria das linguagens projetadas após Pascal (como Ada , Modula e Java ) também oferece suporte a registros.

Operações

  • Declaração de um novo tipo de registro, incluindo a posição, tipo e (possivelmente) nome de cada campo;
  • Declaração de variáveis ​​e valores como tendo um determinado tipo de registro;
  • Construção de um valor de registro a partir de determinados valores de campo e (às vezes) com determinados nomes de campo;
  • Seleção de um campo de um registro com um nome explícito;
  • Atribuição de um valor de registro a uma variável de registro;
  • Comparação de dois registros para igualdade;
  • Cálculo de um valor de hash padrão para o registro.

A seleção de um campo de um valor de registro produz um valor.

Alguns idiomas podem fornecer recursos que enumeram todos os campos de um registro, ou pelo menos os campos que são referências. Esse recurso é necessário para implementar certos serviços, como depuradores , coletores de lixo e serialização . Requer algum grau de polimorfismo de tipo .

Em sistemas com subtipagem de registro, as operações em valores do tipo de registro também podem incluir:

  • Adicionando um novo campo a um registro, definindo o valor do novo campo.
  • Removendo um campo de um registro.

Em tais configurações, um tipo de registro específico implica que um conjunto específico de campos está presente, mas os valores desse tipo podem conter campos adicionais. Um registro com campos x , y e z pertenceria, portanto, ao tipo de registro com campos x e y , da mesma forma que um registro com campos x , y e r . O raciocínio é que passar um registro ( x , y , z ) para uma função que espera um registro ( x , y ) como argumento deve funcionar, uma vez que essa função encontrará todos os campos de que necessita dentro do registro. Muitas maneiras de implementar registros na prática em linguagens de programação teriam problemas em permitir tal variabilidade, mas a questão é uma característica central dos tipos de registro em contextos mais teóricos.

Atribuição e comparação

A maioria das linguagens permite a atribuição entre registros que têm exatamente o mesmo tipo de registro (incluindo os mesmos tipos de campo e nomes, na mesma ordem). Dependendo do idioma, no entanto, dois tipos de dados de registro definidos separadamente podem ser considerados tipos distintos, mesmo que tenham exatamente os mesmos campos.

Algumas linguagens também podem permitir a atribuição entre registros cujos campos têm nomes diferentes, combinando cada valor de campo com a variável de campo correspondente por suas posições no registro; de modo que, por exemplo, um número complexo com campos chamados reale imagpossa ser atribuído a uma variável de registro de ponto 2D com campos Xe Y. Nessa alternativa, os dois operandos ainda precisam ter a mesma sequência de tipos de campo. Alguns idiomas também podem exigir que os tipos correspondentes tenham o mesmo tamanho e codificação, de modo que todo o registro possa ser atribuído como uma sequência de bits não interpretada . Outras linguagens podem ser mais flexíveis a esse respeito e exigem apenas que cada campo de valor possa ser legalmente atribuído ao campo de variável correspondente; de modo que, por exemplo, um campo inteiro curto pode ser atribuído a um campo inteiro longo , ou vice-versa.

Outras linguagens (como COBOL ) podem combinar campos e valores por seus nomes, em vez de posições.

Essas mesmas possibilidades se aplicam à comparação de dois valores de registro de igualdade. Alguns idiomas também podem permitir comparações de ordem ('<' e '>'), usando a ordem lexicográfica com base na comparação de campos individuais.

PL / I permite ambos os tipos de atribuição anteriores e também permite expressões de estrutura , como a = a+1;onde "a" é um registro ou estrutura na terminologia PL / I.

Seleção de campo distributiva de Algol 68

No Algol 68, se Ptsfosse um array de registros, cada um com campos inteiros Xe Y, poderia-se escrever para obter um array de inteiros, consistindo nos campos de todos os elementos de . Como resultado, as declarações e teriam o mesmo efeito. Y of PtsYPtsY of Pts[3] := 7(Y of Pts)[3] := 7

Declaração "com" de Pascal

Na linguagem de programação Pascal , o comando with R do Sexecutaria a seqüência de comandos Scomo se todos os campos do registro Rtivessem sido declarados como variáveis. Então, em vez de escrever, Pt.X := 5; Pt.Y := Pt.X + 3podia-se escrever with Pt do begin X := 5; Y := X + 3 end.

Representação na memória

A representação dos registros na memória varia dependendo das linguagens de programação. Normalmente os campos são armazenados em posições consecutivas na memória, na mesma ordem em que são declarados no tipo de registro. Isso pode resultar em dois ou mais campos armazenados na mesma palavra de memória; na verdade, esse recurso é frequentemente usado na programação de sistemas para acessar bits específicos de uma palavra. Por outro lado, a maioria dos compiladores adicionará campos de preenchimento, em sua maioria invisíveis para o programador, a fim de cumprir as restrições de alinhamento impostas pela máquina - digamos, que um campo de ponto flutuante deve ocupar uma única palavra.

Algumas linguagens podem implementar um registro como uma matriz de endereços apontando para os campos (e, possivelmente, para seus nomes e / ou tipos). Objetos em linguagens orientadas a objetos são frequentemente implementados de maneiras bastante complicadas, especialmente em linguagens que permitem herança múltipla de classes .

Registros de autodefinição

Um registro de autodefinição é um tipo de registro que contém informações para identificar o tipo de registro e localizar informações dentro do registro. Ele pode conter os deslocamentos de elementos; os elementos podem, portanto, ser armazenados em qualquer ordem ou podem ser omitidos. Como alternativa, vários elementos do registro, cada um incluindo um identificador de elemento, podem simplesmente seguir um ao outro em qualquer ordem.

Exemplos

O seguinte mostra exemplos de definições de registro:

  • PL / I:
      declare 1 date,
                2 year  fixed binary,
                2 month fixed binary,
                2 day   fixed binary;
    
  • Algol 68:
  mode date = struct (int year, int month, int day);
  • C:
    struct date {
       int year;
       int month;
       int day;
    };
    
  • Fortran :
    type :: date
       integer :: year, month, day
    end type date
    
  • :
    type Date struct {
            year  int
            month time.Month
            day   int
    }
    
  • Pascal :
    type TDate = record
       Year: Integer;
       Month: 1..12;
       Day: 1..31;
    end;
    
  • Ferrugem :
    struct Date {
        year: u32,
        month: u32,
        day: u32,
    }
    
  • Swift :
    struct Date {
        year: Int,
        month: Int,
        day: Int,
    }
    
  • Haskell :
    data Date = Date { year :: Integer
                     , month :: Integer
                     , day :: Integer
                     }
    
  • Julia :
    struct Date
        year::Int
        month::Int
        day::Int
    end
    
  • ML padrão :
    type date = {year:int, month:int, day:int}
    
  • COBOL :
           01 WS-DATE.
              02 WS-YEAR  PIC 9999.
              02 WS-MONTH PIC 99.
              02 WS-DAY   PIC 99.
    
  • Java 15 :
    record Date(int year, int month, int day) {
        // this is the minimum required    
    }
    
  • Lisp comum :
    (defstruct Date
      (year  0 :type integer)
      (month 1 :type (integer 1 12))
      (day   1 :type (integer 1 31)))
    

Veja também

Referências