Article de reference

Conversion de type

( Découvrez comment et quand supprimer ce message ) En informatique , la conversion de type , le transtypage , la coercition de type , et la jonglerie de types sont différentes ...

( Découvrez comment et quand supprimer ce message )

En informatique , la conversion de type , le transtypage , la coercition de type , et la jonglerie de types sont différentes manières de changer une expression d'un type de données à un autre. Un exemple serait la conversion d'une valeur entière en une valeur à virgule flottante ou sa représentation textuelle sous forme de chaîne , et vice versa. Les conversions de type peuvent tirer parti de certaines fonctionnalités des hiérarchies de types ou des représentations de données . Deux aspects importants d'une conversion de type sont de savoir si elle se produit implicitement (automatiquement) ou explicitement , et si la représentation de données sous-jacente est convertie d'une représentation à une autre, ou si une représentation donnée est simplement réinterprétée comme la représentation d'un autre type de données. En général, les types de données primitifs et composés peuvent être convertis.

Chaque langage de programmation a ses propres règles sur la façon dont les types peuvent être convertis. Les langages à typage fort effectuent généralement peu de conversions implicites et découragent la réinterprétation des représentations, tandis que les langages à typage faible effectuent de nombreuses conversions implicites entre les types de données. Les langages à typage faible permettent souvent de forcer le compilateur à interpréter arbitrairement un élément de données comme ayant des représentations différentes. Il peut s'agir d'une erreur de programmation non évidente ou d'une méthode technique permettant de traiter directement le matériel sous-jacent.

Dans la plupart des langages, le mot coercition est utilisé pour désigner une conversion implicite , soit pendant la compilation, soit pendant l'exécution . Par exemple, dans une expression mélangeant des nombres entiers et à virgule flottante (comme 5 + 0,1), le compilateur convertira automatiquement la représentation entière en représentation à virgule flottante afin que les fractions ne soient pas perdues. Les conversions de type explicites sont indiquées soit en écrivant du code supplémentaire (par exemple en ajoutant des identifiants de type ou en appelant des routines intégrées ), soit en codant des routines de conversion que le compilateur utilisera lorsqu'il s'arrêterait autrement en raison d'une incompatibilité de type.

Dans la plupart des langages de type ALGOL , tels que Pascal , Modula-2 , Ada et Delphi , la conversion et le transtypage sont des concepts nettement différents. Dans ces langages, la conversion fait référence au changement implicite ou explicite d'une valeur d'un format de stockage de type de données à un autre, par exemple un entier de 16 bits en un entier de 32 bits. Les besoins de stockage peuvent changer suite à la conversion, y compris une possible perte de précision ou troncature. Le mot transtypage , en revanche, fait référence au changement explicite de l' interprétation du modèle de bits représentant une valeur d'un type à un autre. Par exemple, 32 bits contigus peuvent être traités comme un tableau de 32 booléens, une chaîne de 4 octets, un entier non signé de 32 bits ou une valeur à virgule flottante simple précision IEEE. Étant donné que les bits stockés ne sont jamais modifiés, le programmeur doit connaître les détails de bas niveau tels que le format de représentation, l'ordre des octets et les besoins d'alignement, pour effectuer un transtypage significatif.

Dans la famille de langages C et ALGOL 68 , le mot cast fait généralement référence à une conversion de type explicite (par opposition à une conversion implicite), ce qui entraîne une certaine ambiguïté quant à savoir s'il s'agit d'une réinterprétation d'un modèle de bits ou d'une conversion réelle de représentation de données. Plus important encore est la multitude de méthodes et de règles qui s'appliquent au type de données (ou à la classe) localisé par un pointeur et à la façon dont un pointeur peut être ajusté par le compilateur dans des cas comme l'héritage d'objet (de classe).

Casting explicite dans différentes langues

Ada

Ada fournit une fonction de bibliothèque générique Unchecked_Conversion.

Langages de type C

Conversion de type implicite

La conversion implicite de type, également appelée coercition ou jonglerie de types , est une conversion automatique de type effectuée par le compilateur . Certains langages de programmation permettent aux compilateurs de fournir une coercition ; d'autres l'exigent.

Dans une expression de type mixte, les données d'un ou plusieurs sous-types peuvent être converties en supertypes selon les besoins lors de l'exécution afin que le programme s'exécute correctement. Par exemple, le code suivant est légal en langage C :

double d ; long l ; int i ;
si ( d > i ) d = i ; si ( i > l ) l = i ; si ( d == l ) d *= 2 ;

Bien que d , l et i appartiennent à des types de données différents, ils seront automatiquement convertis en types de données égaux à chaque fois qu'une comparaison ou une affectation est exécutée. Ce comportement doit être utilisé avec prudence, car des conséquences imprévues peuvent survenir. Des données peuvent être perdues lors de la conversion de représentations de nombres à virgule flottante en nombres entiers, car les composants fractionnaires des valeurs à virgule flottante seront tronqués (arrondis vers zéro). Inversement, la précision peut être perdue lors de la conversion de représentations de nombres entiers en nombres à virgule flottante, car un type à virgule flottante peut être incapable de représenter exactement toutes les valeurs possibles d'un type entier. Par exemple, il peut s'agir d'un type de précision simple IEEE 754 , qui ne peut pas représenter exactement l'entier 16777217, alors qu'un type entier 32 bits le peut. Cela peut conduire à un comportement peu intuitif, comme le montre le code suivant : float

#include <stdio.h>
int main ( void ) { int i_value = 16777217 ; float f_value = 16777216.0 ; printf ( "L'entier est : %d " , i_value ); printf ( "Le float est : %f " , f_value ); printf ( "Leur égalité : %d " , i_value == f_value ); }

Sur les compilateurs qui implémentent les floats en simple précision IEEE et les ints en au moins 32 bits, ce code donnera cette impression particulière :

L'entier est : 16777217 Le flottant est : 16777216.000000 Leur égalité : 1 

Notez que 1 représente l'égalité dans la dernière ligne ci-dessus. Ce comportement étrange est causé par une conversion implicite de i_valueen float lorsqu'il est comparé à f_value. La conversion entraîne une perte de précision, ce qui rend les valeurs égales avant la comparaison.

Points importants à retenir :

  1. floatprovoque intune troncature , c'est-à-dire la suppression de la partie fractionnaire.
  2. doubleprovoque floatl'arrondi des chiffres.
  3. longce intqui entraîne la perte de bits d'ordre supérieur en excès.
Promotion de type

Un cas particulier de conversion de type implicite est la promotion de type, où un objet est automatiquement converti en un autre type de données représentant un sur-ensemble du type d'origine. Les promotions sont généralement utilisées avec des types plus petits que le type natif de l' unité arithmétique et logique (ALU) de la plate-forme cible, avant les opérations arithmétiques et logiques, pour rendre ces opérations possibles, ou plus efficaces si l'ALU peut fonctionner avec plusieurs types. C et C++ effectuent une telle promotion pour les objets de type booléen, caractère, caractère large, énumération et entier court qui sont promus en int, et pour les objets de type float, qui sont promus en double. Contrairement à d'autres conversions de type, les promotions ne perdent jamais en précision et ne modifient jamais la valeur stockée dans l'objet.

En Java :

int x = 3 ; double y = 3.5 ; System . out . println ( x + y ); // La sortie sera 6.5

Conversion de type explicite

La conversion explicite de type, également appelée conversion de type, est une conversion de type qui est définie explicitement dans un programme (au lieu d'être effectuée automatiquement selon les règles du langage pour la conversion implicite de type). Elle est demandée par l'utilisateur dans le programme.

double da = 3.3 ; double db = 3.3 ; double dc = 3.4 ; int result = ( int ) da + ( int ) db + ( int ) dc ; // result == 9 // si une conversion implicite était utilisée (comme avec "result = da + db + dc"), le résultat serait égal à 10

Il existe plusieurs types de conversion explicite.

à carreaux
Avant d'effectuer la conversion, une vérification d'exécution est effectuée pour voir si le type de destination peut contenir la valeur source. Dans le cas contraire, une condition d'erreur est générée.
non vérifié
Aucune vérification n'est effectuée. Si le type de destination ne peut pas contenir la valeur source, le résultat est indéfini.
modèle de bits
La représentation brute des bits de la source est copiée mot pour mot et réinterprétée en fonction du type de destination. Ceci peut également être réalisé via l'aliasing .

Dans les langages de programmation orientés objet , les objets peuvent également être convertis en classes descendantes : une référence d'une classe de base est convertie en l'une de ses classes dérivées.

C# et C++

En C# , la conversion de type peut être effectuée de manière sûre ou non sûre (c'est-à-dire de type C), la première étant appelée conversion de type vérifiée .

Animal animal = nouveau Chat ( );
Bouledogue b = ( Bouledogue ) animal ; // si (animal est Bouledogue), stat.type(animal) est Bouledogue, sinon une exception b = animal comme Bouledogue ; // si (animal est Bouledogue), b = (Bouledogue) animal, sinon b = null
animal = null ; b = animal comme Bulldog ; // b == null

En C++, un effet similaire peut être obtenu en utilisant la syntaxe de conversion de style C++ .

Animal * animal = nouveau Chat ;
Bulldog * b = static_cast < Bulldog *> ( animal ); // compile uniquement si Animal ou Bulldog est dérivé de l'autre (ou du même) b = dynamic_cast < Bulldog *> ( animal ); // si (animal est Bulldog), b = (Bulldog*) animal, sinon b = nullptr
Bulldog & br = static_cast < Bulldog &> ( * animal ); // même que ci-dessus, mais une exception sera levée si un nullptr devait être renvoyé // cela n'apparaît pas dans le code où la gestion des exceptions est évitée
supprimer animal ; // toujours libérer les ressources animal = nullptr ; b = dynamic_cast < Bulldog *> ( animal ); // b == nullptr

Tour Eiffel

Dans Eiffel, la notion de conversion de type est intégrée aux règles du système de types. La règle d'affectation stipule qu'une affectation, telle que :

x := y

est valide si et seulement si le type de son expression source, ydans ce cas, est compatible avec le type de son entité cible, xdans ce cas. Dans cette règle, compatible avec signifie que le type de l'expression source est conforme ou convertit en celui de la cible. La conformité des types est définie par les règles familières du polymorphisme en programmation orientée objet . Par exemple, dans l'affectation ci-dessus, le type de yest conforme au type de xsi la classe sur laquelle yest basée est un descendant de celle sur laquelle xest basée.

Définition de la conversion de type dans Eiffel

Les actions de conversion de type dans Eiffel, en particulier les conversions vers et les conversions depuis, sont définies comme :

Un type basé sur une classe CU se convertit en un type T basé sur une classe CT (et T se convertit à partir de U) si

CT a une procédure de conversion utilisant U comme type de conversion, ou
CU a une requête de conversion répertoriant T comme type de conversion

Exemple

Eiffel est un langage entièrement compatible avec Microsoft .NET Framework . Avant le développement de .NET, Eiffel disposait déjà de bibliothèques de classes étendues. L'utilisation des bibliothèques de types .NET, en particulier avec des types couramment utilisés tels que les chaînes, pose un problème de conversion. Les logiciels Eiffel existants utilisent les classes de chaînes (telles que STRING_8) des bibliothèques Eiffel, mais les logiciels Eiffel écrits pour .NET doivent utiliser la classe de chaînes .NET ( System.String) dans de nombreux cas, par exemple lors de l'appel de méthodes .NET qui attendent que des éléments de type .NET soient transmis en tant qu'arguments. Par conséquent, la conversion de ces types dans les deux sens doit être aussi transparente que possible.

my_string : STRING_8 -- Chaîne Eiffel native my_system_string : SYSTEM_STRING -- Chaîne .NET native
...
ma_chaîne := ma_chaîne_système

Dans le code ci-dessus, deux chaînes sont déclarées, une de chaque type différent ( SYSTEM_STRINGest l'alias conforme à Eiffel pour System.String). Comme System.Stringn'est pas conforme à STRING_8, l'affectation ci-dessus n'est valide que si System.Stringconvertit en STRING_8.

La classe Eiffel STRING_8possède une procédure de conversion make_from_cilpour les objets de type System.String. Les procédures de conversion sont également toujours désignées comme des procédures de création (similaires aux constructeurs). Voici un extrait de la STRING_8classe :

classe STRING_8 ... créer make_from_cil ... convertir make_from_cil ({ SYSTEM_STRING }) ...

La présence de la procédure de conversion rend l'affectation :

ma_chaîne := ma_chaîne_système

sémantiquement équivalent à :

créer ma_chaîne . make_from_cil ( ma_chaîne_système )

dans lequel my_stringest construit comme un nouvel objet de type STRING_8avec un contenu équivalent à celui de my_system_string.

Pour gérer une affectation avec la source et la cible d’origine inversées :

ma_chaîne_système := ma_chaîne

la classe STRING_8contient également une requête de conversion to_cilqui produira un System.Stringà partir d'une instance de STRING_8.

classe STRING_8 ... créer make_from_cil ... convertir make_from_cil ({ SYSTEM_STRING }) en_cil : { SYSTEM_STRING } ...

La mission :

ma_chaîne_système := ma_chaîne

alors, devient équivalent à :

ma_chaîne_système := ma_chaîne . to_cil

Dans Eiffel, la configuration de la conversion de type est incluse dans le code de la classe, mais elle semble ensuite se produire aussi automatiquement que la conversion de type explicite dans le code client. Cela inclut non seulement les affectations, mais également d'autres types de pièces jointes, telles que la substitution d'arguments (paramètres).

Rouiller

Rust ne fournit aucune conversion de type implicite (coercition) entre les types primitifs. Cependant, une conversion de type explicite (casting) peut être effectuée à l'aide du asmot-clé.

laissez x = 1000 ; println! ( "1000 comme u16 est : {}" , x comme u16 );

Assertion de type

Un concept connexe dans les systèmes de types statiques est appelé assertion de type , qui demande au compilateur de traiter l'expression d'un certain type, sans tenir compte de sa propre inférence. L'assertion de type peut être sûre (une vérification d'exécution est effectuée) ou non. Une assertion de type ne convertit pas la valeur d'un type de données en un autre.

Manuscrit

En TypeScript , une assertion de type est effectuée en utilisant le asmot-clé :

const myCanvas = document . getElementById ( "main_canvas" ) as HTMLCanvasElement ;

Dans l'exemple ci-dessus, document.getElementByIdest déclaré pour renvoyer un HTMLElement, mais vous savez qu'il renvoie toujours un HTMLCanvasElement, qui est un sous-type de HTMLElement, dans ce cas. Si ce n'est pas le cas, le code suivant qui repose sur le comportement de HTMLCanvasElementne fonctionnera pas correctement, car dans Typescript, il n'y a pas de vérification d'exécution pour les assertions de type.

En Typescript, il n'existe aucun moyen général de vérifier si une valeur est d'un certain type au moment de l'exécution, car il n'existe pas de prise en charge des types au moment de l'exécution. Cependant, il est possible d'écrire une fonction définie par l'utilisateur qui indique au compilateur si une valeur est d'un certain type ou non. Une telle fonction est appelée type guard , et est déclarée avec un type de retour de x is Type, où xest un paramètre ou this, à la place de boolean.

Cela permet aux assertions de type non sécurisées d'être contenues dans la fonction de vérification au lieu d'être dispersées dans la base de code.

Aller

En Go , une assertion de type peut être utilisée pour accéder à une valeur de type concret à partir d'une valeur d'interface. Il s'agit d'une assertion sûre qui paniquera (dans le cas d'une valeur de retour) ou renverra une valeur nulle (si deux valeurs de retour sont utilisées), si la valeur n'est pas de ce type concret.

t := je .( T )

Ces assertions de type indiquent au système qu'il iest de type T. Si ce n'est pas le cas, il panique.

Casting implicite à l'aide d'unions non étiquetées

De nombreux langages de programmation prennent en charge les types d'union qui peuvent contenir une valeur de plusieurs types. Les unions non marquées sont fournies dans certains langages avec une vérification de type lâche, comme C et PL/I , mais également dans le Pascal d'origine . Elles peuvent être utilisées pour interpréter le modèle de bits d'un type comme une valeur d'un autre type.

Problèmes de sécurité

En piratage informatique , le typage est l'utilisation abusive de la conversion de type pour modifier temporairement le type de données d' une variable par rapport à la manière dont il a été défini à l'origine. Cela offre des opportunités aux pirates informatiques car dans la conversion de type, après qu'une variable a été « typée » pour devenir un type de données différent, le compilateur traitera cette variable piratée comme le nouveau type de données pour cette opération spécifique.

Plus d articles de Worldlex Wiki

Revenez a l index pour explorer davantage de pages sur l histoire, la science, la culture, la geographie et la societe en francais.

Explorer l index