![]() | This article has multiple issues. Please helpimprove it or discuss these issues on thetalk page.(Learn how and when to remove these messages) (Learn how and when to remove this message)
|
Incomputer science,type conversion,[1][2]type casting,[1][3]type coercion,[3] andtype juggling[4][5] are different ways of changing anexpression from onedata type to another. An example would be the conversion of aninteger value into afloating point value or its textual representation as astring, and vice versa. Type conversions can take advantage of certain features oftype hierarchies ordata representations. Two important aspects of a type conversion are whether it happensimplicitly (automatically) orexplicitly,[1][6] and whether the underlying data representation is converted from one representation into another, or a given representation is merelyreinterpreted as the representation of another data type.[6][7] In general, bothprimitive andcompound data types can be converted.
Eachprogramming language has its own rules on how types can be converted. Languages withstrong typing typically do little implicit conversion and discourage the reinterpretation of representations, while languages withweak typing perform many implicit conversions between data types. Weak typing language often allow forcing thecompiler to arbitrarily interpret a data item as having different representations—this can be a non-obvious programming error, or a technical method to directly deal with underlying hardware.
In most languages, the wordcoercion is used to denote animplicit conversion, either during compilation or duringrun time. For example, in an expression mixing integer and floating point numbers (like 5 + 0.1), the compiler will automatically convert integer representation into floating point representation so fractions are not lost. Explicit type conversions are either indicated by writing additional code (e.g. adding type identifiers or calling built-inroutines) or by coding conversion routines for the compiler to use when it otherwise would halt with a type mismatch.
In mostALGOL-like languages, such asPascal,Modula-2,Ada andDelphi,conversion andcasting are distinctly different concepts. In these languages,conversion refers to either implicitly or explicitly changing a value from one data type storage format to another, e.g. a 16-bit integer to a 32-bit integer. The storage needs may change as a result of the conversion, including a possible loss of precision or truncation. The wordcast, on the other hand, refers to explicitly changing theinterpretation of thebit pattern representing a value from one type to another. For example, 32 contiguous bits may be treated as an array of 32 Booleans, a 4-byte string, an unsigned 32-bit integer or an IEEE single precision floating point value. Because the stored bits are never changed, the programmer must know low level details such as representation format, byte order, and alignment needs, to meaningfully cast.
In the C family of languages andALGOL 68, the wordcast typically refers to anexplicit type conversion (as opposed to an implicit conversion), causing some ambiguity about whether this is a re-interpretation of a bit-pattern or a real data representation conversion. More important is the multitude of ways and rules that apply to what data type (or class) is located by a pointer and how a pointer may be adjusted by the compiler in cases like object (class) inheritance.
Ada provides a generic library function Unchecked_Conversion.[8]
Implicit type conversion, also known ascoercion ortype juggling, is an automatic type conversion by thecompiler. Someprogramming languages allow compilers to provide coercion; others require it.
In a mixed-type expression, data of one or moresubtypes can beconverted to a supertype as needed atruntime so that the program will run correctly. For example, the following is legalC language code:
doubled;longl;inti;if(d>i)d=i;if(i>l)l=i;if(d==l)d*=2;
Althoughd,l, andi belong to different data types, they will be automatically converted to equal data types each time a comparison or assignment is executed. This behavior should be used with caution, as unintended consequences can arise. Data can be lost when converting representations from floating-point to integer, as the fractional components of the floating-point values will be truncated (rounded toward zero). Conversely, precision can be lost when converting representations from integer to floating-point, since a floating-point type may be unable to exactly represent all possible values of some integer type. For example,float
might be anIEEE 754 single precision type, which cannot represent the integer 16777217 exactly, while a 32-bit integer type can. This can lead to unintuitive behavior, as demonstrated by the following code:
#include<stdio.h>intmain(void){inti_value=16777217;floatf_value=16777216.0;printf("The integer is: %d\n",i_value);printf("The float is: %f\n",f_value);printf("Their equality: %d\n",i_value==f_value);}
On compilers that implement floats as IEEE single precision, and ints as at least 32 bits, this code will give this peculiar print-out:
The integer is: 16777217The float is: 16777216.000000Their equality: 1
Note that 1 represents equality in the last line above. This odd behavior is caused by an implicit conversion ofi_value
to float when it is compared withf_value
. The conversion causes loss of precision, which makes the values equal before the comparison.
Important takeaways:
float
toint
causestruncation, i.e., removal of the fractional part.double
tofloat
causes rounding of digit.long
toint
causes dropping of excess higher order bits.One special case of implicit type conversion is type promotion, where an object is automatically converted into another data type representing asuperset of the original type. Promotions are commonly used with types smaller than the native type of the target platform'sarithmetic logic unit (ALU), before arithmetic and logical operations, to make such operations possible, or more efficient if the ALU can work with more than one type. C and C++ perform such promotion for objects of Boolean, character, wide character, enumeration, and short integer types which are promoted to int, and for objects of type float, which are promoted to double. Unlike some other type conversions, promotions never lose precision or modify the value stored in the object.
InJava:
intx=3;doubley=3.5;System.out.println(x+y);// The output will be 6.5
Explicit type conversion, also called type casting, is a type conversion which is explicitly defined within a program (instead of being done automatically according to the rules of the language for implicit type conversion). It is requested by the user in the program.
doubleda=3.3;doubledb=3.3;doubledc=3.4;intresult=(int)da+(int)db+(int)dc;// result == 9// if implicit conversion would be used (as with "result = da + db + dc"), result would be equal to 10
There are several kinds of explicit conversion.
Inobject-oriented programming languages, objects can also bedowncast : a reference of a base class is cast to one of its derived classes.
InC#, type conversion can be made in a safe or unsafe (i.e., C-like) manner, the former calledchecked type cast.[9]
Animalanimal=newCat();Bulldogb=(Bulldog)animal;// if (animal is Bulldog), stat.type(animal) is Bulldog, else an exceptionb=animalasBulldog;// if (animal is Bulldog), b = (Bulldog) animal, else b = nullanimal=null;b=animalasBulldog;// b == null
InC++ a similar effect can be achieved usingC++-style cast syntax.
Animal*animal=newCat;Bulldog*b=static_cast<Bulldog*>(animal);// compiles only if either Animal or Bulldog is derived from the other (or same)b=dynamic_cast<Bulldog*>(animal);// if (animal is Bulldog), b = (Bulldog*) animal, else b = nullptrBulldog&br=static_cast<Bulldog&>(*animal);// same as above, but an exception will be thrown if a nullptr was to be returned// this is not seen in code where exception handling is avoideddeleteanimal;// always free resourcesanimal=nullptr;b=dynamic_cast<Bulldog*>(animal);// b == nullptr
InEiffel the notion of type conversion is integrated into the rules of the type system. The Assignment Rule says that an assignment, such as:
x:=y
is valid if and only if the type of its source expression,y
in this case, iscompatible with the type of its target entity,x
in this case. In this rule,compatible with means that the type of the source expression eitherconforms to orconverts to that of the target. Conformance of types is defined by the familiar rules forpolymorphism in object-oriented programming. For example, in the assignment above, the type ofy
conforms to the type ofx
if the class upon whichy
is based is a descendant of that upon whichx
is based.
The actions of type conversion in Eiffel, specificallyconverts to andconverts from are defined as:
A type based on a class CUconverts to a type T based on a class CT (and Tconverts from U) if either
- CT has aconversion procedure using U as a conversion type, or
- CU has aconversion query listing T as a conversion type
Eiffel is a fully compliantlanguage for Microsoft.NET Framework. Before development of .NET, Eiffel already had extensive class libraries. Using the .NET type libraries, particularly with commonly used types such as strings, poses a conversion problem. Existing Eiffel software uses the string classes (such asSTRING_8
) from the Eiffel libraries, but Eiffel software written for .NET must use the .NET string class (System.String
) in many cases, for example when calling .NET methods which expect items of the .NET type to be passed as arguments. So, the conversion of these types back and forth needs to be as seamless as possible.
my_string:STRING_8-- Native Eiffel stringmy_system_string:SYSTEM_STRING-- Native .NET string...my_string:=my_system_string
In the code above, two strings are declared, one of each different type (SYSTEM_STRING
is the Eiffel compliant alias for System.String). BecauseSystem.String
does not conform toSTRING_8
, then the assignment above is valid only ifSystem.String
converts toSTRING_8
.
The Eiffel classSTRING_8
has a conversion proceduremake_from_cil
for objects of typeSystem.String
. Conversion procedures are also always designated as creation procedures (similar to constructors). The following is an excerpt from theSTRING_8
class:
classSTRING_8...createmake_from_cil...convertmake_from_cil({SYSTEM_STRING})...
The presence of the conversion procedure makes the assignment:
my_string:=my_system_string
semantically equivalent to:
createmy_string.make_from_cil(my_system_string)
in whichmy_string
is constructed as a new object of typeSTRING_8
with content equivalent to that ofmy_system_string
.
To handle an assignment with original source and target reversed:
my_system_string:=my_string
the classSTRING_8
also contains a conversion queryto_cil
which will produce aSystem.String
from an instance ofSTRING_8
.
classSTRING_8...createmake_from_cil...convertmake_from_cil({SYSTEM_STRING})to_cil:{SYSTEM_STRING}...
The assignment:
my_system_string:=my_string
then, becomes equivalent to:
my_system_string:=my_string.to_cil
In Eiffel, the setup for type conversion is included in the class code, but then appears to happen as automatically asexplicit type conversion in client code. The includes not just assignments but other types of attachments as well, such as argument (parameter) substitution.
Rust provides no implicit type conversion (coercion) between primitive types. But, explicit type conversion (casting) can be performed using theas
keyword.[10]
letx=1000;println!("1000 as a u16 is: {}",xasu16);
A related concept in static type systems is calledtype assertion, which instruct the compiler to treat the expression of a certain type, disregarding its own inference. Type assertion may be safe (a runtime check is performed) or unsafe. A type assertion does not convert the value from a data type to another.
InTypeScript, a type assertion is done by using theas
keyword:[11]
constmyCanvas=document.getElementById("main_canvas")asHTMLCanvasElement;
In the above example,document.getElementById
is declared to return anHTMLElement
, but you know that it always return anHTMLCanvasElement
, which is a subtype ofHTMLElement
, in this case. If it is not the case, subsequent code which relies on the behaviour ofHTMLCanvasElement
will not perform correctly, as in Typescript there is no runtime checking for type assertions.
In Typescript, there is no general way to check if a value is of a certain type at runtime, as there is no runtime type support. However, it is possible to write a user-defined function which the user tells the compiler if a value is of a certain type of not. Such a function is calledtype guard, and is declared with a return type ofx is Type
, wherex
is a parameter orthis
, in place ofboolean
.
This allows unsafe type assertions to be contained in the checker function instead of littered around the codebase.
InGo, a type assertion can be used to access a concrete type value from an interface value. It is a safe assertion that it will panic (in the case of one return value), or return a zero value (if two return values are used), if the value is not of that concrete type.[12]
t:=i.(T)
This type assertions tell the system thati
is of typeT
. If it isn't, it panics.
Many programming languages supportunion types which can hold a value of multiple types.Untagged unions are provided in some languages with loose type-checking, such asC andPL/I, but also in the originalPascal. These can be used to interpret the bit pattern of one type as a value of another type.
Inhacking, typecasting is the misuse of type conversion to temporarily change avariable's data type from how it was originally defined.[13] This provides opportunities for hackers since in type conversion after a variable is "typecast" to become a different data type, the compiler will treat that hacked variable as the new data type for that specific operation.[14]