stringtranslate.com

Conversión de tipos

En informática , la conversión de tipos , [1] [2] la conversión de tipos , [1] [3] la coerción de tipos , [3] y el malabarismo de tipos [4] [5] son ​​diferentes formas de cambiar una expresión de un tipo de datos a otro. Un ejemplo sería la conversión de un valor entero en un valor de punto flotante o su representación textual como una cadena , y viceversa. Las conversiones de tipos pueden aprovechar ciertas características de las jerarquías de tipos o las representaciones de datos . Dos aspectos importantes de una conversión de tipos son si ocurre de forma implícita (automática) o explícita , [1] [6] y si la representación de datos subyacente se convierte de una representación a otra, o una representación dada simplemente se reinterpreta como la representación de otro tipo de datos. [6] [7] En general, se pueden convertir tanto los tipos de datos primitivos como los compuestos .

Cada lenguaje de programación tiene sus propias reglas sobre cómo se pueden convertir los tipos. Los lenguajes con tipado fuerte suelen realizar pocas conversiones implícitas y desalientan la reinterpretación de representaciones, mientras que los lenguajes con tipado débil realizan muchas conversiones implícitas entre tipos de datos. Los lenguajes con tipado débil suelen permitir forzar al compilador a interpretar arbitrariamente un elemento de datos como si tuviera diferentes representaciones; esto puede ser un error de programación no obvio o un método técnico para tratar directamente con el hardware subyacente.

En la mayoría de los lenguajes, la palabra coerción se utiliza para denotar una conversión implícita , ya sea durante la compilación o durante el tiempo de ejecución . Por ejemplo, en una expresión que mezcla números enteros y de punto flotante (como 5 + 0,1), el compilador convertirá automáticamente la representación entera en representación de punto flotante para que no se pierdan las fracciones. Las conversiones de tipo explícitas se indican escribiendo código adicional (por ejemplo, agregando identificadores de tipo o llamando a rutinas integradas ) o codificando rutinas de conversión para que el compilador las use cuando de lo contrario se detendría con una falta de coincidencia de tipos.

En la mayoría de los lenguajes similares a ALGOL , como Pascal , Modula-2 , Ada y Delphi , la conversión y el casting son conceptos claramente diferentes. En estos lenguajes, la conversión se refiere a cambiar implícita o explícitamente un valor de un formato de almacenamiento de tipo de datos a otro, por ejemplo, un entero de 16 bits a un entero de 32 bits. Las necesidades de almacenamiento pueden cambiar como resultado de la conversión, incluida una posible pérdida de precisión o truncamiento. La palabra cast , por otro lado, se refiere a cambiar explícitamente la interpretación del patrón de bits que representa un valor de un tipo a otro. Por ejemplo, 32 bits contiguos pueden tratarse como una matriz de 32 booleanos, una cadena de 4 bytes, un entero de 32 bits sin signo o un valor de punto flotante de precisión simple IEEE. Debido a que los bits almacenados nunca se cambian, el programador debe conocer detalles de bajo nivel como el formato de representación, el orden de bytes y las necesidades de alineación, para realizar un casting significativo.

En la familia de lenguajes C y ALGOL 68 , la palabra conversión generalmente se refiere a una conversión de tipo explícita (en oposición a una conversión implícita), lo que genera cierta ambigüedad sobre si se trata de una reinterpretación de un patrón de bits o una conversión de representación de datos reales. Más importante es la multitud de formas y reglas que se aplican a qué tipo de datos (o clase) se ubica mediante un puntero y cómo el compilador puede ajustar un puntero en casos como la herencia de objetos (clases).

Casting explícito en varios idiomas

Ada

Ada proporciona una función de biblioteca genérica Unchecked_Conversion. [8]

Lenguajes similares a C

Conversión de tipo implícita

La conversión de tipos implícita, también conocida como coerción o manipulación de tipos , es una conversión de tipos automática realizada por el compilador . Algunos lenguajes de programación permiten que los compiladores proporcionen coerción; otros la requieren.

En una expresión de tipo mixto, los datos de uno o más subtipos se pueden convertir a un supertipo según sea necesario en tiempo de ejecución para que el programa se ejecute correctamente. Por ejemplo, el siguiente es un código de lenguaje C válido :

doble d ; largo l ; int i ;   si ( d > i ) d = i ; si ( i > l ) l = i ; si ( d == l ) d *= 2 ;                  

Aunque d , l e i pertenecen a tipos de datos diferentes, se convertirán automáticamente a tipos de datos iguales cada vez que se ejecute una comparación o asignación. Este comportamiento debe usarse con precaución, ya que pueden surgir consecuencias no deseadas . Se pueden perder datos al convertir representaciones de punto flotante a entero, ya que los componentes fraccionarios de los valores de punto flotante se truncarán (se redondearán hacia cero). Por el contrario, se puede perder precisión al convertir representaciones de entero a punto flotante, ya que un tipo de punto flotante puede no ser capaz de representar exactamente todos los valores posibles de algún tipo entero. Por ejemplo, podría ser un tipo de precisión simple IEEE 754 , que no puede representar exactamente el entero 16777217, mientras que un tipo entero de 32 bits sí puede. Esto puede conducir a un comportamiento poco intuitivo, como lo demuestra el siguiente código:float

#incluir <stdio.h> int main ( void ) { int i_value = 16777217 ; float f_value = 16777216.0 ; printf ( "El entero es: %d \n " , i_value ); printf ( "El float es: %f \n " , f_value ); printf ( "Su igualdad: %d \n " , i_value == f_value ); }                 

En los compiladores que implementan números flotantes como precisión simple IEEE y números enteros como al menos 32 bits, este código dará esta peculiar impresión:

El entero es: 16777217El flotante es: 16777216.000000Su igualdad: 1

Tenga en cuenta que 1 representa la igualdad en la última línea anterior. Este comportamiento extraño se debe a una conversión implícita de i_valuea float cuando se compara con f_value. La conversión provoca una pérdida de precisión, lo que hace que los valores sean iguales antes de la comparación.

Conclusiones importantes:

  1. floatprovoca inttruncamiento , es decir, eliminación de la parte fraccionaria.
  2. doubleProvoca floatredondeo de dígitos.
  3. longpara intprovocar la caída de bits sobrantes de orden superior.
Promoción de tipo

Un caso especial de conversión de tipo implícita es la promoción de tipo, en la que un objeto se convierte automáticamente en otro tipo de datos que representa un superconjunto del tipo original. Las promociones se utilizan habitualmente con tipos más pequeños que el tipo nativo de la unidad lógica aritmética (ALU) de la plataforma de destino, antes de las operaciones aritméticas y lógicas, para hacer que dichas operaciones sean posibles o más eficientes si la ALU puede trabajar con más de un tipo. C y C++ realizan dicha promoción para objetos de tipo booleano, de carácter, de carácter ancho, de enumeración y de entero corto que se promueven a int, y para objetos de tipo float, que se promueven a double. A diferencia de otras conversiones de tipo, las promociones nunca pierden precisión ni modifican el valor almacenado en el objeto.

En Java :

int x = 3 ; double y = 3.5 ; System . out . println ( x + y ); // La salida será 6.5         

Conversión de tipo explícita

La conversión de tipos explícita, también llamada conversión de tipos, es una conversión de tipos que se define explícitamente dentro de un programa (en lugar de realizarse automáticamente según las reglas del lenguaje para la conversión de tipos implícita). La solicita el usuario en el programa.

double da = 3.3 ; double db = 3.3 ; double dc = 3.4 ; int result = ( int ) da + ( int ) db + ( int ) dc ; // result == 9 // si se utilizara una conversión implícita (como con "result = da + db + dc"), result sería igual a 10                 

Hay varios tipos de conversión explícita.

comprobado
Antes de realizar la conversión, se realiza una comprobación en tiempo de ejecución para ver si el tipo de destino puede contener el valor de origen. De lo contrario, se genera una condición de error.
desenfrenado
No se realiza ninguna comprobación. Si el tipo de destino no puede contener el valor de origen, el resultado no está definido.
patrón de bits
La representación de bits sin procesar de la fuente se copia textualmente y se reinterpreta según el tipo de destino. Esto también se puede lograr mediante aliasing .

En los lenguajes de programación orientados a objetos , los objetos también pueden ser convertidos a una versión inferior  : una referencia de una clase base se convierte a una de sus clases derivadas.

C# y C++

En C# , la conversión de tipos se puede realizar de manera segura o insegura (es decir, similar a C), la primera llamada conversión de tipos comprobada . [9]

Animal animal = nuevo Gato ();    Bulldog b = ( Bulldog ) animal ; // si (animal es Bulldog), stat.type(animal) es Bulldog, de lo contrario una excepción b = animal como Bulldog ; // si (animal es Bulldog), b = (Bulldog) animal, de lo contrario b = null          animal = null ; b = animal como Bulldog ; // b == null       

En C++ se puede lograr un efecto similar utilizando la sintaxis de conversión al estilo C++ .

Animal * animal = nuevo Gato ;    Bulldog * b = static_cast < Bulldog *> ( animal ); // compila solo si Animal o Bulldog se deriva del otro (o del mismo) b = dynamic_cast < Bulldog *> ( animal ); // si (animal es Bulldog), b = (Bulldog*) animal, de lo contrario b = nullptr       Bulldog & br = static_cast < Bulldog &> ( * animal ); // igual que el anterior, pero se lanzará una excepción si se devuelve un valor nulo // esto no se ve en el código donde se evita el manejo de excepciones     eliminar animal ; // siempre libera recursos animal = nullptr ; b = dynamic_cast < Bulldog *> ( animal ); // b == nullptr       

Torre Eiffel

En Eiffel, la noción de conversión de tipos está integrada en las reglas del sistema de tipos. La regla de asignación dice que una asignación, como:

x := y  

es válido si y solo si el tipo de su expresión de origen, yen este caso, es compatible con el tipo de su entidad de destino, xen este caso. En esta regla, compatible con significa que el tipo de la expresión de origen se ajusta o se convierte al de destino. La conformidad de los tipos se define mediante las conocidas reglas de polimorfismo en la programación orientada a objetos . Por ejemplo, en la tarea anterior, el tipo de yse ajusta al tipo de xsi la clase en la que yse basa es descendiente de aquella en la que xse basa.

Definición de conversión de tipos en Eiffel

Las acciones de conversión de tipo en Eiffel, específicamente convierte a y convierte desde, se definen como:

Un tipo basado en una clase CU se convierte en un tipo T basado en una clase CT (y T se convierte de U) si

CT tiene un procedimiento de conversión que utiliza U como tipo de conversión, o
CU tiene una consulta de conversión que enumera T como tipo de conversión

Ejemplo

Eiffel es un lenguaje totalmente compatible con Microsoft .NET Framework . Antes del desarrollo de .NET, Eiffel ya contaba con extensas bibliotecas de clases. El uso de las bibliotecas de tipos .NET, en particular con tipos de uso común como cadenas, plantea un problema de conversión. El software Eiffel existente utiliza las clases de cadena (como STRING_8) de las bibliotecas Eiffel, pero el software Eiffel escrito para .NET debe utilizar la clase de cadena .NET ( System.String) en muchos casos, por ejemplo, al llamar a métodos .NET que esperan que se pasen elementos del tipo .NET como argumentos. Por lo tanto, la conversión de estos tipos de un lado a otro debe ser lo más fluida posible.

 my_string : STRING_8 -- Cadena Eiffel nativa my_system_string : SYSTEM_STRING -- Cadena .NET nativa      ... mi_cadena := mi_cadena_del_sistema  

En el código anterior, se declaran dos cadenas, una de cada tipo diferente ( SYSTEM_STRINGes el alias compatible con Eiffel para System.String). Debido a que System.Stringno se ajusta a STRING_8, la asignación anterior solo es válida si System.Stringse convierte a STRING_8.

La clase Eiffel STRING_8tiene un procedimiento de conversión make_from_cilpara objetos de tipo System.String. Los procedimientos de conversión también se designan siempre como procedimientos de creación (similares a los constructores). A continuación, se incluye un extracto de la STRING_8clase:

 clase STRING_8 ... crear make_from_cil ... convertir make_from_cil ({ SYSTEM_STRING }) ...         

La presencia del procedimiento de conversión hace que la asignación:

 mi_cadena := mi_cadena_del_sistema  

semánticamente equivalente a:

 crear mi_cadena .make_from_cil ( mi_cadena_del_sistema )  

en el que my_stringse construye como un nuevo objeto de tipo STRING_8con contenido equivalente al de my_system_string.

Para gestionar una tarea con el origen y el destino originales invertidos:

 mi_cadena_del_sistema := mi_cadena  

La clase STRING_8también contiene una consulta de conversión to_cilque producirá un System.Stringa partir de una instancia de STRING_8.

 clase STRING_8 ... crear make_from_cil ... convertir make_from_cil ({ SYSTEM_STRING }) a_cil : { SYSTEM_STRING } ...           

La tarea:

 mi_cadena_del_sistema := mi_cadena  

entonces, se vuelve equivalente a:

 mi_cadena_del_sistema : = mi_cadena .to_cil  

En Eiffel, la configuración para la conversión de tipos está incluida en el código de clase, pero luego parece que se produce de forma tan automática como la conversión de tipos explícita en el código del cliente. Esto incluye no solo asignaciones, sino también otros tipos de adjuntos, como la sustitución de argumentos (parámetros).

Óxido

Rust no ofrece conversión de tipos implícita (coerción) entre tipos primitivos. Sin embargo, se puede realizar una conversión de tipos explícita (casting) utilizando la aspalabra clave. [10]

sea ​​x = 1000 ; println! ( "1000 como u16 es: {}" , x como u16 );      

Afirmación de tipo

Un concepto relacionado en los sistemas de tipos estáticos se denomina aserción de tipo , que indica al compilador que trate la expresión de un tipo determinado, sin tener en cuenta su propia inferencia. La aserción de tipo puede ser segura (se realiza una comprobación en tiempo de ejecución) o insegura. Una aserción de tipo no convierte el valor de un tipo de datos a otro.

Mecanografiado

En TypeScript , una afirmación de tipo se realiza mediante la aspalabra clave: [11]

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

En el ejemplo anterior, document.getElementByIdse declara que devuelve un HTMLElement, pero se sabe que siempre devuelve un HTMLCanvasElement, que es un subtipo de HTMLElement, en este caso. Si no es el caso, el código posterior que se basa en el comportamiento de HTMLCanvasElementno se ejecutará correctamente, ya que en Typescript no hay comprobación en tiempo de ejecución de las afirmaciones de tipo.

En Typescript, no existe una forma general de verificar si un valor es de un tipo determinado en tiempo de ejecución, ya que no hay soporte de tipos en tiempo de ejecución. Sin embargo, es posible escribir una función definida por el usuario que le indique al compilador si un valor es de un tipo determinado o no. Dicha función se denomina protección de tipo y se declara con un tipo de retorno de x is Type, donde xes un parámetro o this, en lugar de boolean.

Esto permite que las afirmaciones de tipo inseguras se contengan en la función de verificación en lugar de estar dispersas en el código base.

Ir

En Go , se puede utilizar una aserción de tipo para acceder a un valor de tipo concreto desde un valor de interfaz. Es una aserción segura que se generará una alarma (en el caso de un valor de retorno), o que devolverá un valor cero (si se utilizan dos valores de retorno), si el valor no es de ese tipo concreto. [12]

t := yo .( T )  

Estas aserciones de tipo le indican al sistema que ies de tipo T. Si no lo es, entra en pánico.

Conversión implícita mediante uniones sin etiquetar

Muchos lenguajes de programación admiten tipos de unión que pueden contener un valor de varios tipos. En algunos lenguajes con verificación de tipos flexible, como C y PL/I , pero también en el Pascal original , se proporcionan uniones sin etiquetar . Se pueden utilizar para interpretar el patrón de bits de un tipo como un valor de otro tipo.

Problemas de seguridad

En el ámbito del hacking , la conversión de tipos es el uso indebido de la conversión de tipos para cambiar temporalmente el tipo de datos de una variable con respecto a cómo se definió originalmente. [13] Esto ofrece oportunidades a los hackers, ya que en la conversión de tipos, después de que una variable se "convierte" para convertirse en un tipo de datos diferente, el compilador tratará esa variable pirateada como el nuevo tipo de datos para esa operación específica. [14]

Véase también

Referencias

  1. ^ abc Mehrotra, Dheeraj (2008). Ciencias de la computación de S. Chand . S. Chand. págs. 81–83. ISBN 978-8121929844.
  2. ^ Lenguajes de programación: diseño y construcción . Publicaciones Laxmi. 2013. pág. 35. ISBN 978-9381159415.
  3. ^ ab Reilly, Edwin (2004). Enciclopedia concisa de informática. John Wiley & Sons. pp. 82, 110. ISBN 0470090952.
  4. ^ Fenton, Steve (2017). Pro TypeScript: desarrollo de JavaScript a escala de aplicaciones . Apress. pp. xxiii. ISBN 978-1484232491.
  5. ^ "PHP: Malabarismo con tipos - Manual" . php.net . Consultado el 27 de enero de 2019 .
  6. ^ ab Olsson, Mikael (2013). Referencia rápida de sintaxis de C++ . Apress. págs. 87–89. ISBN 978-1430262770.
  7. ^ Kruse, Rudolf; Borgelt, cristiano; Braune, cristiano; Mostaghim, Sanaz; Steinbrecher, Matthias (16 de septiembre de 2016). Inteligencia computacional: una introducción metodológica . Saltador. pag. 269.ISBN 978-1447172963.
  8. ^ "Conversiones de tipo no controladas". Ada Information Clearinghouse . Consultado el 11 de marzo de 2023 .
  9. ^ Mössenböck, Hanspeter (25 de marzo de 2002). "C# avanzado: conversiones de tipo marcadas" (PDF) . Institut für Systemsoftware, Johannes Kepler Universität Linz, Fachbereich Informatik. pag. 5 . Consultado el 4 de agosto de 2011 .en Tutorial de C#
  10. ^ "Fundición - Rust con ejemplos". doc.rust-lang.org .
  11. ^ ""Documentación de Typescript"".
  12. ^ ""Un recorrido por Go"".
  13. ^ Jon Erickson Hacking, 2.ª edición: El arte de la explotación 2008 1593271441 pág. 51 "La conversión de tipos es simplemente una forma de cambiar temporalmente el tipo de datos de una variable, a pesar de cómo se definió originalmente. Cuando se convierte una variable a un tipo diferente, básicamente se le indica al compilador que trate esa variable como si fuera el nuevo tipo de datos, pero solo para esa operación. La sintaxis para la conversión de tipos es la siguiente: (typecast_data_type) variable ..."
  14. ^ Arpita Gopal Magnifying C 2009 8120338618 p. 59 "De lo anterior se desprende claramente que el uso de la conversión de tipos consiste en hacer que una variable de un tipo actúe como si fuera de otro tipo para una única operación. Por lo tanto, al utilizar esta capacidad de conversión de tipos, es posible crear caracteres ASCII mediante la conversión de tipos enteros a su... "

Enlaces externos