Conversão de tipo

Em ciência da computação , conversão de tipo , [1] [2] conversão de tipo , [1] [3] coerção de tipo , [3] e malabarismo de tipo [4] [5] são maneiras diferentes de alterar uma expressão de um tipo de dados para outro. Um exemplo seria a conversão de um valor inteiro em um valor de ponto flutuante ou sua representação textual como uma string , e vice-versa. As conversões de tipo podem tirar proveito de certos recursos de hierarquias de tipo ou representações de dados . Dois aspectos importantes de uma conversão de tipo são se ela acontece implicitamente (automaticamente) ou explicitamente , [1] [6] e se a representação de dados subjacente é convertida de uma representação para outra, ou uma determinada representação é meramente reinterpretada como a representação de outro tipo de dados. [6] [7] Em geral, tipos de dados primitivos e compostos podem ser convertidos.

Cada linguagem de programação tem suas próprias regras sobre como os tipos podem ser convertidos. Linguagens com tipagem forte geralmente fazem pouca conversão implícita e desencorajam a reinterpretação de representações, enquanto linguagens com tipagem fraca realizam muitas conversões implícitas entre tipos de dados. Linguagens de tipagem fraca geralmente permitem forçar o compilador a interpretar arbitrariamente um item de dados como tendo representações diferentes — isso pode ser um erro de programação não óbvio ou um método técnico para lidar diretamente com o hardware subjacente.

Na maioria das linguagens, a palavra coerção é usada para denotar uma conversão implícita , seja durante a compilação ou durante o tempo de execução . Por exemplo, em uma expressão que mistura números inteiros e de ponto flutuante (como 5 + 0,1), o compilador converterá automaticamente a representação inteira em representação de ponto flutuante para que frações não sejam perdidas. Conversões de tipo explícitas são indicadas escrevendo código adicional (por exemplo, adicionando identificadores de tipo ou chamando rotinas internas ) ou codificando rotinas de conversão para o compilador usar quando, de outra forma, ele pararia com uma incompatibilidade de tipo.

Na maioria das linguagens do tipo ALGOL , como Pascal , Modula-2 , Ada e Delphi , conversão e conversão são conceitos distintamente diferentes. Nessas linguagens, conversão se refere a alterar implícita ou explicitamente um valor de um formato de armazenamento de tipo de dados para outro, por exemplo, um inteiro de 16 bits para um inteiro de 32 bits. As necessidades de armazenamento podem mudar como resultado da conversão, incluindo uma possível perda de precisão ou truncamento. A palavra conversão , por outro lado, se refere a alterar explicitamente a interpretação do padrão de bits que representa um valor de um tipo para outro. Por exemplo, 32 bits contíguos podem ser tratados como uma matriz de 32 booleanos, uma string de 4 bytes, um inteiro de 32 bits sem sinal ou um valor de ponto flutuante de precisão simples IEEE. Como os bits armazenados nunca são alterados, o programador deve conhecer detalhes de baixo nível, como formato de representação, ordem de bytes e necessidades de alinhamento, para fazer uma conversão significativa.

Na família de linguagens C e ALGOL 68 , a palavra cast normalmente se refere a uma conversão de tipo explícita (em oposição a uma conversão implícita), causando alguma ambiguidade sobre se esta é uma reinterpretação de um padrão de bits ou uma conversão de representação de dados real. Mais importante é a multiplicidade de maneiras e regras que se aplicam a qual tipo de dado (ou classe) é localizado por um ponteiro e como um ponteiro pode ser ajustado pelo compilador em casos como herança de objeto (classe).

Elenco explícito em vários idiomas

Ada

Ada fornece uma função de biblioteca genérica Unchecked_Conversion. [8]

Linguagens do tipo C

Conversão de tipo implícita

Conversão implícita de tipo, também conhecida como coerção ou malabarismo de tipo , é uma conversão automática de tipo pelo compilador . Algumas linguagens de programação permitem que os compiladores forneçam coerção; outras exigem isso.

Em uma expressão de tipo misto, dados de um ou mais subtipos podem ser convertidos para um supertipo conforme necessário em tempo de execução para que o programa seja executado corretamente. Por exemplo, o seguinte é um código de linguagem C legal :

duplo d ; longo l ; int i ;  
    
     

se ( d > i ) d = i ; se ( i > l ) l = i ; se ( d == l ) d *= 2 ;        
        
       

Embora d , l e i pertençam a tipos de dados diferentes, eles serão automaticamente convertidos em tipos de dados iguais sempre que uma comparação ou atribuição for executada. Esse comportamento deve ser usado com cautela, pois consequências não intencionais podem surgir. Dados podem ser perdidos ao converter representações de ponto flutuante para inteiro, pois os componentes fracionários dos valores de ponto flutuante serão truncados (arredondados para zero). Por outro lado, a precisão pode ser perdida ao converter representações de inteiro para ponto flutuante, pois um tipo de ponto flutuante pode ser incapaz de representar exatamente todos os valores possíveis de algum tipo inteiro. Por exemplo, pode ser um tipo de precisão simples IEEE 754 , que não pode representar o inteiro 16777217 exatamente, enquanto um tipo inteiro de 32 bits pode. Isso pode levar a um comportamento não intuitivo, conforme demonstrado pelo código a seguir: float

#incluir <stdio.h> 

int main ( void ) { int i_value = 16777217 ; float f_value = 16777216.0 ; printf ( "O inteiro é: %d \n " , i_value ); printf ( "O float é: %f \n " , f_value ); printf ( "Sua igualdade: %d \n " , i_value == f_value ); } 

         
       
     
     
       

Em compiladores que implementam floats como precisão simples IEEE e ints como pelo menos 32 bits, este código fornecerá esta impressão peculiar:

O inteiro é: 16777217
O float é: 16777216.000000
Sua igualdade: 1

Note que 1 representa igualdade na última linha acima. Esse comportamento estranho é causado por uma conversão implícita de i_valuepara float quando comparado com f_value. A conversão causa perda de precisão, o que torna os valores iguais antes da comparação.

Conclusões importantes:

  1. floatpara intcausar truncamento , ou seja, remoção da parte fracionária.
  2. doublepara floatcausar arredondamento do dígito.
  3. longpara intcausar a queda de bits de ordem superior em excesso.
Promoção de tipo

Um caso especial de conversão implícita de tipo é a promoção de tipo, onde um objeto é automaticamente convertido em outro tipo de dado representando um superconjunto do tipo original. Promoções são comumente usadas com tipos menores que o tipo nativo da unidade lógica aritmética (ALU) da plataforma de destino, antes de operações aritméticas e lógicas, para tornar tais operações possíveis, ou mais eficientes se a ALU puder trabalhar com mais de um tipo. C e C++ realizam tal promoção para objetos de tipos Boolean, character, wide character, enumeration e short integer que são promovidos para int, e para objetos do tipo float, que são promovidos para double. Ao contrário de algumas outras conversões de tipo, promoções nunca perdem precisão ou modificam o valor armazenado no objeto.

Em Java :

int x = 3 ; double y = 3.5 ; Sistema . out . println ( x + y ); // A saída será 6.5   
   
   

Conversão de tipo explícita

Conversão de tipo explícita, também chamada de conversão de tipo, é uma conversão de tipo que é explicitamente definida dentro de um programa (em vez de ser feita automaticamente de acordo com as regras da linguagem para conversão de tipo implícita). Ela é solicitada pelo usuário no programa.

double da = 3.3 ; double db = 3.3 ; double dc = 3.4 ; int result = ( int ) da + ( int ) db + ( int ) dc ; // result == 9 // se a conversão implícita fosse usada (como com "result = da + db + dc"), result seria igual a 10   
   
   
        

Existem vários tipos de conversão explícita.

verificado
Antes da conversão ser realizada, uma verificação de tempo de execução é feita para ver se o tipo de destino pode conter o valor de origem. Se não, uma condição de erro é levantada.
não verificado
Nenhuma verificação é realizada. Se o tipo de destino não puder conter o valor de origem, o resultado será indefinido.
padrão de bits
A representação bruta de bits da fonte é copiada verbatim, e é reinterpretada de acordo com o tipo de destino. Isso também pode ser alcançado via aliasing .

Em linguagens de programação orientadas a objetos , os objetos também podem ser convertidos  : uma referência de uma classe base é convertida para uma de suas classes derivadas.

C# e C++

Em C# , a conversão de tipos pode ser feita de forma segura ou insegura (ou seja, semelhante a C), sendo a primeira chamada de conversão de tipo verificada . [9]

Animal animal = novo Gato ( );    

Bulldog b = ( Bulldog ) animal ; // se (animal for Bulldog), stat.type(animal) for Bulldog, senão uma exceção b = animal como Bulldog ; // se (animal for Bulldog), b = (Bulldog) animal, senão b = null      
             

animal = nulo ; b = animal como Bulldog ; // b == nulo  
             

Em C++, um efeito semelhante pode ser alcançado usando a sintaxe de conversão no estilo C++ .

Animal * animal = novo Gato ;    

Bulldog * b = static_cast < Bulldog *> ( animal ); // compila somente se Animal ou Bulldog for derivado do outro (ou do mesmo) b = dynamic_cast < Bulldog *> ( animal ); // se (animal for Bulldog), b = (Bulldog*) animal, senão b = nullptr    
           

Bulldog & br = static_cast < Bulldog &> ( * animal ); // o mesmo que acima, mas uma exceção será lançada se um nullptr for retornado // isso não é visto no código onde o tratamento de exceções é evitado    
                                              

delete animal ; // sempre recursos livres animal = nullptr ; b = dynamic_cast < Bulldog *> ( animal ); // b == nullptr  
  
           

Torre Eiffel

Em Eiffel, a noção de conversão de tipo é integrada às regras do sistema de tipo. A Regra de Atribuição diz que uma atribuição, como:

x := y  

é válido se e somente se o tipo de sua expressão de origem, yneste caso, for compatível com o tipo de sua entidade de destino, xneste caso. Nesta regra, compatível com significa que o tipo da expressão de origem está em conformidade com ou converte para aquele do destino. A conformidade de tipos é definida pelas regras familiares para polimorfismo em programação orientada a objetos . Por exemplo, na atribuição acima, o tipo de yestá em conformidade com o tipo de xse a classe na qual yé baseado for descendente daquela na qual xé baseado.

Definição de conversão de tipo em Eiffel

As ações de conversão de tipo em Eiffel, especificamente converte para e converte de, são definidas como:

Um tipo baseado em uma classe CU converte-se em um tipo T baseado em uma classe CT (e T converte de U) se

CT tem um procedimento de conversão usando U como tipo de conversão, ou
CU tem uma consulta de conversão listando T como um tipo de conversão

Exemplo

Eiffel é uma linguagem totalmente compatível com o Microsoft .NET Framework . Antes do desenvolvimento do .NET, Eiffel já tinha bibliotecas de classes extensas. Usar as bibliotecas de tipos .NET, particularmente com tipos comumente usados, como strings, apresenta um problema de conversão. O software Eiffel existente usa as classes de string (como STRING_8) das bibliotecas Eiffel, mas o software Eiffel escrito para .NET deve usar a classe de string .NET ( System.String) em muitos casos, por exemplo, ao chamar métodos .NET que esperam que itens do tipo .NET sejam passados ​​como argumentos. Portanto, a conversão desses tipos para frente e para trás precisa ser o mais perfeita possível.

    my_string : STRING_8 -- String nativa do Eiffel my_system_string : SYSTEM_STRING -- String nativa do .NET                  
          

        ...

            minha_string := minha_string_do_sistema  

No código acima, duas strings são declaradas, uma de cada tipo diferente ( SYSTEM_STRINGé o alias compatível com Eiffel para System.String). Como System.Stringnão está em conformidade com STRING_8, então a atribuição acima é válida somente se System.Stringconverte para STRING_8.

A classe Eiffel STRING_8tem um procedimento de conversão make_from_cilpara objetos do tipo System.String. Procedimentos de conversão também são sempre designados como procedimentos de criação (similares a construtores). O seguinte é um trecho da STRING_8classe:

    classe STRING_8 ... criar make_from_cil ... converter make_from_cil ({ SYSTEM_STRING }) ... 
        
    
        
        
    
         
        

A presença do procedimento de conversão torna a atribuição:

            minha_string := minha_string_do_sistema  

semanticamente equivalente a:

            crie minha_string . make_from_cil ( minha_string_do_sistema )  

no qual my_stringé construído como um novo objeto do tipo STRING_8com conteúdo equivalente ao de my_system_string.

Para manipular uma tarefa com fonte original e destino invertidos:

            minha_string_do_sistema := minha_string  

a classe STRING_8também contém uma consulta de conversão to_cilque produzirá um System.Stringa partir de uma instância de STRING_8.

    classe STRING_8 ... criar make_from_cil ... converter make_from_cil ({ SYSTEM_STRING }) para_cil : { SYSTEM_STRING } ... 
        
    
        
        
    
         
         
        

A tarefa:

            minha_string_do_sistema := minha_string  

então, torna-se equivalente a:

            minha_string_do_sistema := minha_string . to_cil  

Em Eiffel, a configuração para conversão de tipo é incluída no código da classe, mas então parece acontecer tão automaticamente quanto a conversão de tipo explícita no código do cliente. Isso inclui não apenas atribuições, mas também outros tipos de anexos, como substituição de argumento (parâmetro).

Ferrugem

Rust não fornece conversão de tipo implícita (coerção) entre tipos primitivos. Mas, a conversão de tipo explícita (casting) pode ser realizada usando a aspalavra-chave. [10]

deixe x = 1000 ; println! ( "1000 como u16 é: {}" , x como u16 );   
   

Asserção de tipo

Um conceito relacionado em sistemas de tipos estáticos é chamado de asserção de tipo , que instrui o compilador a tratar a expressão de um certo tipo, desconsiderando sua própria inferência. A asserção de tipo pode ser segura (uma verificação de tempo de execução é realizada) ou insegura. Uma asserção de tipo não converte o valor de um tipo de dados para outro.

TypeScript

No TypeScript , uma asserção de tipo é feita usando a aspalavra-chave: [11]

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

No exemplo acima, document.getElementByIdé declarado para retornar um HTMLElement, mas você sabe que ele sempre retorna um HTMLCanvasElement, que é um subtipo de HTMLElement, neste caso. Se não for o caso, o código subsequente que depende do comportamento de HTMLCanvasElementnão será executado corretamente, pois no Typescript não há verificação de tempo de execução para asserções de tipo.

No Typescript, não há uma maneira geral de verificar se um valor é de um determinado tipo em tempo de execução, pois não há suporte a tipos de tempo de execução. No entanto, é possível escrever uma função definida pelo usuário que informa ao compilador se um valor é de um determinado tipo ou não. Essa função é chamada de type guard e é declarada com um tipo de retorno de x is Type, onde xé um parâmetro ou this, no lugar de boolean.

Isso permite que asserções de tipos inseguros sejam contidas na função de verificação em vez de espalhadas pela base de código.

Ir

Em Go , uma asserção de tipo pode ser usada para acessar um valor de tipo concreto de um valor de interface. É uma asserção segura que ele entrará em pânico (no caso de um valor de retorno), ou retornará um valor zero (se dois valores de retorno forem usados), se o valor não for desse tipo concreto. [12]

t := eu .( T )  

Este tipo de asserção diz ao sistema que ié do tipo T. Se não for, ele entra em pânico.

Conversão implícita usando uniões não marcadas

Muitas linguagens de programação suportam tipos de união que podem conter um valor de vários tipos. Uniões não marcadas são fornecidas em algumas linguagens com verificação de tipo frouxa, como C e PL/I , mas também no Pascal original . Elas podem ser usadas para interpretar o padrão de bits de um tipo como um valor de outro tipo.

Problemas de segurança

Em hacking , typecasting é o uso indevido da conversão de tipos para alterar temporariamente o tipo de dados de uma variável de como ele foi originalmente definido. [13] Isso fornece oportunidades para hackers, pois na conversão de tipos, depois que uma variável é "typecast" para se tornar um tipo de dados diferente, o compilador tratará essa variável hackeada como o novo tipo de dados para essa operação específica. [14]

Veja também

Referências

  1. ^ abc Mehrotra, Dheeraj (2008). Ciência da Computação de S. Chand . S. Chand. pp. 81–83. ISBN 978-8121929844.
  2. ^ Linguagens de Programação - Design e Construções . Publicações Laxmi. 2013. p. 35. ISBN 978-9381159415.
  3. ^ ab Reilly, Edwin (2004). Enciclopédia Concisa de Ciência da Computação. John Wiley & Sons. pp. 82, 110. ISBN 0470090952.
  4. ^ Fenton, Steve (2017). Pro TypeScript: Desenvolvimento JavaScript em escala de aplicativo . Apress. pp. xxiii. ISBN 978-1484232491.
  5. ^ "PHP: Type Juggling - Manual". php.net . Recuperado em 27 de janeiro de 2019 .
  6. ^ ab Olsson, Mikael (2013). Referência rápida de sintaxe C++ . Aperte. págs. 87–89. ISBN 978-1430262770.
  7. ^ Kruse, Rodolfo; Borgelt, cristão; Braune, cristão; Mostaghim, Sanaz; Steinbrecher, Matthias (16 de setembro de 2016). Inteligência Computacional: Uma Introdução Metodológica . Springer. pág. 269. ISBN 978-1447172963.
  8. ^ "Conversões de Tipo Não Verificadas". Ada Information Clearinghouse . Recuperado em 11 de março de 2023 .
  9. ^ Mössenböck, Hanspeter (25 de março de 2002). "C # avançado: conversões de tipo verificadas" (PDF) . Instituto de Software de Sistemas, Johannes Kepler Universität Linz, Fachbereich Informatik. pág. 5 . Recuperado em 4 de agosto de 2011 . no tutorial C#
  10. ^ "Fundição - Ferrugem por exemplo". doc.rust-lang.org .
  11. ^ ""Documentação do Typescript"".
  12. ^ ""Um tour pelo Go"".
  13. ^ Jon Erickson Hacking, 2ª edição: The Art of Exploitation 2008 1593271441 p51 "Typecasting é simplesmente uma maneira de alterar temporariamente o tipo de dados de uma variável, apesar de como ela foi definida originalmente. Quando uma variável é typecast em um tipo diferente, o compilador é basicamente instruído a tratar essa variável como se fosse o novo tipo de dados, mas apenas para essa operação. A sintaxe para typecasting é a seguinte: (typecast_data_type) variável ..."
  14. ^ Arpita Gopal Magnifying C 2009 8120338618 p. 59 "Do exposto acima, fica claro que o uso do typecasting é fazer com que uma variável de um tipo aja como outro tipo para uma única operação. Então, usando essa habilidade do typecasting, é possível criar caracteres ASCII por typecasting de inteiros para seus ..."
  • Fundição em Ada
  • Fundição em C++
  • Guia de referência C++ Por que eu odeio operadores de conversão C++, por Danny Kalev
  • Fundição em Java
  • Conversões implícitas em C#
  • Conversão de tipo implícita em Cppreference.com
  • Castings estáticos e de reinterpretação em C++
  • Upcasting e Downcasting em F#
Obtido em "https://pt.wikipedia.org/w/index.php?title=Conversão_de_tipo&oldid=1253200355#Conversão_de_tipo_implícita"