En informatique , un enregistrement (également appelé structure , struct ou type de données composé ) est une structure de données composite – un ensemble de champs , éventuellement de types de données différents , généralement fixes en nombre et en séquence.
Par exemple, une date peut être stockée sous forme d'enregistrement contenant un champ d'année numérique , un champ de mois représenté par une chaîne et un champ de jour du mois numérique. Un enregistrement de cercle peut contenir un rayon numérique et un centre qui est un enregistrement de point contenant des coordonnées x et y .
Les applications notables incluent le type d'enregistrement du langage de programmation et le stockage basé sur les lignes, les données organisées sous forme de séquence d'enregistrements, comme une table de base de données , une feuille de calcul ou un fichier de valeurs séparées par des virgules (CSV). En général, une valeur de type d'enregistrement est stockée en mémoire et le stockage basé sur les lignes est dans la mémoire de masse .
Un type d'enregistrement est un type de données qui décrit de telles valeurs et variables. La plupart des langages de programmation modernes permettent au programmeur de définir de nouveaux types d'enregistrement. La définition comprend la spécification du type de données de chaque champ et un identifiant (nom ou étiquette) par lequel il est possible d'y accéder. Dans la théorie des types , les types de produits (sans nom de champ) sont généralement préférés en raison de leur simplicité, mais les types d'enregistrement appropriés sont étudiés dans des langages tels que System F-sub . Étant donné que les enregistrements théoriques des types peuvent contenir des champs de type fonction de première classe en plus des données, ils peuvent exprimer de nombreuses fonctionnalités de la programmation orientée objet .
Terminologie
Dans le contexte du stockage, comme dans une base de données ou une feuille de calcul, un enregistrement est souvent appelé une ligne et chaque champ est appelé une colonne .
Dans la programmation orientée objet , un objet est un enregistrement qui contient des champs d'état et de méthode.
Un enregistrement est similaire à un tuple mathématique , bien qu'un tuple puisse ou non être considéré comme un enregistrement, et vice versa, en fonction des conventions et du langage de programmation. Dans la même optique, un type d'enregistrement peut être considéré comme l'analogue en langage informatique du produit cartésien de deux ou plusieurs ensembles mathématiques , ou comme l'implémentation d'un type de produit abstrait dans un langage spécifique.
Un enregistrement diffère d'un tableau dans la mesure où les éléments d'un enregistrement (champs) sont déterminés par la définition de l'enregistrement et peuvent être hétérogènes, tandis qu'un tableau est une collection d'éléments du même type.
Les paramètres d'une fonction peuvent être considérés collectivement comme les champs d'un enregistrement et le passage d'arguments à la fonction peut être considéré comme l'affectation des paramètres d'entrée aux champs d'enregistrement. À un niveau bas, un appel de fonction comprend un enregistrement d'activation ou une trame d'appel , qui contient les paramètres ainsi que d'autres champs tels que les variables locales et l'adresse de retour.
Histoire

Le concept d'enregistrement remonte à divers types de tables et de registres utilisés en comptabilité depuis des temps reculés. La notion moderne d'enregistrement en informatique, avec des champs de type et de taille bien définis, était déjà implicite dans les calculatrices mécaniques du XIXe siècle, telles que la machine analytique de Babbage .

Le support lisible par machine utilisé à l'origine pour les données (par opposition au contrôle) était la carte perforée utilisée pour les enregistrements du recensement des États-Unis de 1890 : chaque carte perforée était un enregistrement unique. Comparez l'entrée de journal de 1880 et la carte perforée de 1895. Les enregistrements étaient bien établis dans la première moitié du 20e siècle, lorsque la plupart des traitements de données étaient effectués à l'aide de cartes perforées. En règle générale, chaque enregistrement d'un fichier de données était enregistré sur une carte perforée, avec des colonnes spécifiques attribuées à des champs spécifiques. En général, un enregistrement était la plus petite unité pouvant être lue à partir d'un stockage externe (par exemple, un lecteur de carte, une bande ou un disque). Le contenu des enregistrements de type carte perforée était à l'origine appelé « enregistrements unitaires » car les cartes perforées avaient des longueurs de document prédéterminées. Lorsque les systèmes de stockage sont devenus plus avancés avec l'utilisation de disques durs et de bandes magnétiques , les enregistrements de longueur variable sont devenus la norme. Un enregistrement de longueur variable est un enregistrement dans lequel la taille de l'enregistrement en octets est approximativement égale à la somme des tailles de ses champs. Cela n’était pas possible avant l’invention d’un matériel de stockage plus avancé, car toutes les cartes perforées devaient être conformes à des longueurs de documents prédéterminées que l’ordinateur pouvait lire, car à l’époque, les cartes devaient être physiquement introduites dans une machine.
La plupart des implémentations de langage machine et des premiers langages assembleurs n'avaient pas de syntaxe spéciale pour les enregistrements, mais le concept était disponible (et largement utilisé) grâce à l'utilisation de registres d'index , d'adressage indirect et de code auto-modifiable . Certains des premiers ordinateurs, comme l' IBM 1620 , disposaient d'un support matériel pour délimiter les enregistrements et les champs, et d'instructions spéciales pour copier ces enregistrements.
Le concept d'enregistrements et de champs était central dans certains des premiers utilitaires de tri et de tabulation de fichiers , tels que Report Program Generator (RPG) d'IBM .
COBOL a été le premierlangage de programmationà prendre en charge les types d'enregistrementset ses fonctions de définition d'enregistrements étaient assez sophistiquées à l'époque. Le langage permet la définition d'enregistrements imbriqués avec des champs alphanumériques, entiers et fractionnaires de taille et de précision arbitraires, ainsi que des champs qui formatent automatiquement toute valeur qui leur est attribuée (par exemple, l'insertion de signes monétaires, de points décimaux et de séparateurs de groupes de chiffres). Chaque fichier est associé à une variable d'enregistrement dans laquelle les données sont lues ou écrites. COBOL fournit également uneMOVE
CORRESPONDINGinstruction qui attribue les champs correspondants de deux enregistrements en fonction de leurs noms.
Les premiers langages développés pour le calcul numérique, comme FORTRAN (jusqu'à FORTRAN IV ) et ALGOL 60 , ne prenaient pas en charge les types d'enregistrements ; mais les versions ultérieures de ces langages, comme FORTRAN 77 et ALGOL 68, les ont ajoutés. Le langage de programmation Lisp d'origine manquait également d'enregistrements (à l'exception de la cellule cons intégrée ), mais ses expressions S fournissaient un substitut adéquat. Le langage de programmation Pascal a été l'un des premiers langages à intégrer complètement les types d'enregistrements avec d'autres types de base dans un système de types logiquement cohérent. Le langage PL/I fournissait des enregistrements de style COBOL. Le langage C fournit le concept d'enregistrement en utilisant structs. La plupart des langages conçus après Pascal (tels que Ada , Modula et Java ) prenaient également en charge les enregistrements.
Bien que les enregistrements ne soient plus souvent utilisés dans leur contexte d'origine (c'est-à-dire utilisés uniquement dans le but de contenir des données), les enregistrements ont influencé les nouveaux langages de programmation orientés objet et les systèmes de gestion de bases de données relationnelles . Étant donné que les enregistrements offrent plus de modularité dans la manière dont les données sont stockées et traitées, ils sont mieux adaptés à la représentation de concepts complexes et réels que les types de données primitifs fournis par défaut dans les langages. Cela a influencé les langages ultérieurs tels que C++ , Python , JavaScript et Objective-C qui répondent aux mêmes besoins de modularité de la programmation. Les objets dans ces langages sont essentiellement des enregistrements avec l'ajout de méthodes et d'héritage , qui permettent aux programmeurs de manipuler la manière dont les données se comportent au lieu du seul contenu d'un enregistrement. De nombreux programmeurs considèrent désormais les enregistrements comme obsolètes, car les langages orientés objet ont des fonctionnalités qui dépassent de loin ce dont les enregistrements sont capables. D'un autre côté, de nombreux programmeurs soutiennent que la faible surcharge et la possibilité d'utiliser des enregistrements en langage assembleur rendent les enregistrements toujours pertinents lors de la programmation avec de faibles niveaux d' abstraction . Aujourd'hui, les langages les plus populaires de l' index TIOBE , un indicateur de la popularité des langages de programmation, ont été influencés d'une certaine manière par les enregistrements en raison du fait qu'ils sont orientés objet. Les langages de requête tels que SQL et Object Query Language ont également été influencés par le concept d'enregistrements. Ces langages permettent au programmeur de stocker des ensembles de données, qui sont essentiellement des enregistrements, dans des tables. Ces données peuvent ensuite être récupérées à l'aide d'une clé primaire . Les tables elles-mêmes sont également des enregistrements qui peuvent avoir une clé étrangère : une clé qui référence des données dans une autre table.
Type d'enregistrement
Opérations
Les opérations pour un type d’enregistrement incluent :
- Déclaration d'un type d'enregistrement, incluant la position, le type et (éventuellement) le nom de chaque champ
- Déclaration d'un enregistrement ; une variable typée comme un type d'enregistrement
- Construction d'une valeur d'enregistrement ; éventuellement avec initialisation de la valeur du champ
- Lire et écrire la valeur du champ d'enregistrement
- Comparaison de deux enregistrements pour l'égalité
- Calcul d'une valeur de hachage standard pour l'enregistrement
Certains langages proposent des fonctionnalités qui énumèrent les champs d'un enregistrement. Cette fonctionnalité est nécessaire pour implémenter certains services tels que le débogage , la récupération de place et la sérialisation . Elle nécessite un certain degré de polymorphisme de type .
Dans les contextes qui prennent en charge le sous-typage d'enregistrement, les opérations incluent l'ajout et la suppression de champs d'un enregistrement. Un type d'enregistrement spécifique implique qu'un ensemble spécifique de champs est présent, mais les valeurs de ce type peuvent contenir des champs supplémentaires. Un enregistrement avec les champs x , y et z appartiendrait donc au type d'enregistrements avec les champs x et y , tout comme un enregistrement avec les champs x , y et r . La raison est que le passage d'un enregistrement ( x , y , z ) à une fonction qui attend un enregistrement ( x , y ) comme argument devrait fonctionner, puisque cette fonction trouvera tous les champs dont elle a besoin dans l'enregistrement. De nombreuses façons d'implémenter concrètement les enregistrements dans les langages de programmation auraient du mal à autoriser une telle variabilité, mais le problème est une caractéristique centrale des types d'enregistrement dans des contextes plus théoriques.
Affectation et comparaison
La plupart des langages permettent l'affectation entre enregistrements qui ont exactement le même type d'enregistrement (y compris les mêmes types et noms de champs, dans le même ordre). Cependant, selon le langage, deux types de données d'enregistrement définis séparément peuvent être considérés comme des types distincts même s'ils ont exactement les mêmes champs.
Certains langages peuvent également autoriser l'affectation entre des enregistrements dont les champs ont des noms différents, en faisant correspondre chaque valeur de champ avec la variable de champ correspondante en fonction de leurs positions dans l'enregistrement ; de sorte que, par exemple, un nombre complexe avec des champs appelés realet imagpeut être affecté à une variable d'enregistrement de points 2D avec des champs Xet Y. Dans cette alternative, les deux opérandes doivent toujours avoir la même séquence de types de champs. Certains langages peuvent également exiger que les types correspondants aient la même taille et le même codage, de sorte que l'enregistrement entier puisse être affecté sous la forme d'une chaîne de bits non interprétée . D'autres langages peuvent être plus flexibles à cet égard et exiger uniquement que chaque champ de valeur puisse être légalement affecté au champ de variable correspondant ; de sorte que, par exemple, un champ entier court puisse être affecté à un champ entier long , ou vice versa.
D'autres langages (tels que COBOL ) peuvent faire correspondre les champs et les valeurs par leurs noms, plutôt que par leurs positions.
Ces mêmes possibilités s'appliquent à la comparaison de deux valeurs d'enregistrement pour l'égalité. Certaines langues peuvent également autoriser les comparaisons d'ordre ('<' et '>'), en utilisant l' ordre lexicographique basé sur la comparaison de champs individuels.
PL/I autorise les deux types d'affectation précédents, ainsi que les expressions de structure , telles que a = a+1;lorsque « a » est un enregistrement ou une structure dans la terminologie PL/I.
Sélection de champ distributif d'Algol 68
Dans Algol 68, si Ptsétait un tableau d'enregistrements, chacun avec des champs entiers Xet Y, on pouvait écrire pour obtenir un tableau d'entiers, constitué des champs de tous les éléments de . Par conséquent, les instructions et auraient le même effet. Y of PtsYPtsY of Pts[3] := 7(Y of Pts)[3] := 7
L'énoncé « avec » de Pascal
En Pascal , la commande with R do Sexécuterait la séquence de commandes Scomme si tous les champs de l'enregistrement Ravaient été déclarés comme variables. De la même manière que pour entrer un espace de noms différent dans un langage orienté objet comme C# , il n'est plus nécessaire d'utiliser le nom de l'enregistrement comme préfixe pour accéder aux champs. Ainsi, au lieu d'écrire, Pt.X := 5; Pt.Y := Pt.X + 3on pourrait écrire . withPtdobeginX:=5;Y:=X+3end
Représentation en mémoire
La représentation d'un enregistrement en mémoire varie en fonction du langage de programmation. Souvent, les champs sont stockés dans des emplacements mémoire consécutifs, dans le même ordre que celui dans lequel ils sont déclarés dans le type d'enregistrement. Cela peut entraîner le stockage de deux champs ou plus dans le même mot de mémoire. En effet, cette fonctionnalité est souvent utilisée dans la programmation système pour accéder à des bits spécifiques d'un mot. D'un autre côté, la plupart des compilateurs ajouteront des champs de remplissage, la plupart du temps invisibles pour le programmeur, afin de se conformer aux contraintes d'alignement imposées par la machine (par exemple, qu'un champ à virgule flottante doit occuper un seul mot).
Certains langages peuvent implémenter un enregistrement sous la forme d'un tableau d'adresses pointant vers les champs (et, éventuellement, vers leurs noms et/ou types). Les objets dans les langages orientés objet sont souvent implémentés de manière assez compliquée, en particulier dans les langages qui autorisent l'héritage de classes multiples .
Enregistrements autodéfinis
Un enregistrement auto-défini est un type d'enregistrement qui contient des informations permettant d'identifier le type d'enregistrement et de localiser des informations dans l'enregistrement. Il peut contenir les décalages des éléments ; les éléments peuvent donc être stockés dans n'importe quel ordre ou peuvent être omis. Les informations stockées dans un enregistrement auto-défini peuvent être interprétées comme des métadonnées pour l'enregistrement, ce qui est similaire à ce que l'on s'attendrait à trouver dans les métadonnées UNIX concernant un fichier, contenant des informations telles que l'heure de création de l'enregistrement et la taille de l'enregistrement en octets . Alternativement, divers éléments de l'enregistrement, chacun comprenant un identifiant d'élément, peuvent simplement se suivre dans n'importe quel ordre.
Champ clé
Un enregistrement, en particulier dans le contexte d'un stockage basé sur des lignes, peut inclure des champs clés qui permettent d'indexer les enregistrements d'une collection. Une clé primaire est unique dans tous les enregistrements stockés ; une seule de ces clés existe. En d'autres termes, aucun doublon ne peut exister pour une clé primaire. Par exemple, un fichier d'employé peut contenir le numéro d'employé, le nom, le service et le salaire. Le numéro d'employé sera unique dans l'organisation et sera la clé primaire. Selon le support de stockage et l'organisation du fichier, le numéro d'employé peut être indexé , c'est-à-dire également stocké dans un fichier séparé pour accélérer la recherche. Le code de service n'est pas nécessairement unique ; il peut également être indexé, auquel cas il serait considéré comme une clé secondaire ou une clé alternative . S'il n'est pas indexé, l'intégralité du fichier d'employé devra être analysée pour produire une liste de tous les employés d'un service spécifique. Les clés sont généralement choisies de manière à minimiser les chances que plusieurs valeurs soient mappées de manière réalisable par une clé. Par exemple, le champ salaire ne serait normalement pas considéré comme utilisable comme clé puisque de nombreux employés auront probablement le même salaire.