Típuskonverzió ( typecasting , kényszer ) – az informatikában egy típusú érték átalakítása egy másik típusú értékre .
Léteznek típusfeliratok:
Az explicit szereposztást a programozó határozza meg a program szövegében a következőképpen:
Az implicit szereposztást fordító ( fordító vagy tolmács ) hajtja végre a nyelvi szabványban leírt szabályok szerint. A legtöbb nyelvi szabvány tiltja az implicit konverziót.
A gyengén tipizált objektumorientált nyelvekben, mint például a C++ , az öröklési mechanizmus úgy valósul meg, hogy az aktuális objektumra mutató mutató típusát az alaposztályba öntik (a típusbiztos nyelvekben , mint például az OCaml , a típusöntés fogalma alapvetően hiányzik, és az altípus-komponensre való hivatkozás megengedhetőségét a konzisztencia-ellenőrző mechanizmus típusai ellenőrzik fordításkor, és a közvetlen hozzáférés a gépi kódban marad).
Az implicit típusú öntés a következő esetekben fordul elő [1] :
Például egy bináris aritmetikai művelet végrehajtásakor az operandusok értékei ugyanabba a típusba kerülnek. Az öröklődés során a származtatott osztálymutatók az alaposztálymutatókba kerülnek.
Vegyünk egy példát C nyelven .
dupla d ; // valós típus long l ; // egész szám típusa int i ; // egész típus ha ( d > i ) d = i ; ha ( i > l ) l = i ; ha ( d == l ) d *= 2 ;Összehasonlítási műveletek végrehajtásakor és hozzárendeléskor a különböző típusú változók implicit módon ugyanahhoz a típushoz kerülnek.
Az implicit konverzióknak mellékhatásai lehetnek. Például, ha egy szám valós típusát egész típusba öntjük, a tört részt levágjuk (a kerekítés nem történik meg) [2] . A fordított konverzió csökkentheti a pontosságot a valós és egész számok megjelenítési különbségei miatt. Például egy típusváltozóban ( IEEE 754 egyszeres pontosságú lebegőpontos szám ) a 16 777 217 szám nem tárolható a pontosság elvesztése nélkül, de egy 32 bites egész típusú változóban igen. A pontosság elvesztése miatt az egész és valós típusokkal (például és ) reprezentált azonos számú összehasonlítási műveletek hamis eredményt adhatnak (a számok nem egyenlőek). float intintfloat
#include <stdio.h> int main ( érvénytelen ) { int i_value = 16777217 ; float f_value = 16777216.0 ; printf ( "Az egész szám:%d \n " , i_érték ); printf ( "A lebegés: %f \n " , f_érték ); printf ( "Egyenlőségük:%d \n " , i_érték == f_érték ); }A fenti kód a következőt adja ki, ha a mérete 32 bites, és a fordító támogatja az IEEE 754 szabványt : int
Az egész szám: 16777217 Az úszószám: 16777216.000000 Egyenlõségük: 1Explicit típus-öntés esetén a típusnév zárójelben van megadva a változó vagy kifejezés előtt. Vegyünk egy példát.
int X ; int Y = 200 ; szén C = 30 ; X = ( int ) C * 10 + Y ; // A C változó az int típusba kerülAz utolsó kifejezés kiértékeléséhez a fordító valami ilyesmit tesz:
Még így is előfordulhatnak hibák. A típus lehet aláírt ( ) vagy előjel nélküli ( ); az eredmény a fordító megvalósításától függ, és ezt a viselkedést a szabvány megengedi. Az előjel nélküli típus értéke az előjeles típusra konvertálva negatívnak bizonyulhat egyes processzorokon a gépi utasítások megvalósítása miatt . A félreértések elkerülése érdekében ajánlatos kifejezetten megadni az előjelességet a típushoz . charsigned charunsigned charcharintchar
Öt explicit típusú konverziós operátor van a C++- ban. Az első művelet, a zárójelek ( ) támogatottak a C -vel való kompatibilitás fenntartása érdekében . A maradék négy műveletet a következőképpen írjuk le (type_to)expression_from
xxx_cast < type_to >( kifejezés_ból )Vegyünk egy példát.
y = static_cast < signed short > ( 65534 ); // az y változó -2-re lesz állítvaA nehézkes kulcsszavak emlékeztetik a programozót, hogy a típusöntés tele van problémákkal.
Művelet static_castCél: Érvényes dobások.
A művelet egy kivétellel hasonló a zárójeles művelethez: nem ad mutatót nem kapcsolódó típusokra (a műveletet erre használják ). static_castreinterpret_cast
Alkalmazás:
Korlátozások expression_from: nem.
Korlátozások a type_tokövetkezőre: Biztosítani kell egy módot a kifejezés értékének expression_fromtípusra type_to, használóra operator type_tovagy konstruktorra való konvertálására.
A művelet előállít -e kódot: Általában igen (például túlterhelt cast vagy konstruktor művelet meghívása). static_cast
Logikai hibák forrásai: attól függ, hogy mit fog kezdeni a művelettel. Túlcsordulás, hatótávolságon kívüli, sőt (mutatókonverziók esetén) memóriakárosodás is lehetséges.
Példák.
// Találatszázalék lekérése. dupla billenő ( const int aHitCount , // találatok száma const int aShotCount // lövések száma ) { if ( aShotCount == 0 ) return 0.0 ; // A duplájára történő átküldés a valós (nem egész) osztás végrehajtásához történik static_cast < double > ( aHitCount * 100 ) / static_cast < double > ( aShotCount ); } // a következő sorok egyenértékűek // a static_cast művelet használata string s = static_cast < string > ( "Helló!" ); // konstruktor meghívása egy argumentummal string s = string ( "Hello!" ); // a zárójelek használatával műveleti string s = ( string ) "Hello!" ; string s = static_cast < string > ( 5 ); // nem fordít, a fordító nem talál megfelelő konstruktort Művelet dynamic_castCél: az öröklődési hierarchia lebontása, speciális viselkedéssel, ha az objektum nem a kívánt típusú.
A művelet az RTTIexpression_from segítségével szerez információkat az objektum típusáról . Ha a típus vagy annak altípusa, akkor az öntést végrehajtják. Másképp: type_to
Korlátozások expression_from: A kifejezésnek hivatkozásnak vagy mutatónak kell lennie egy olyan objektumra, amely legalább egy virtuális funkcióval rendelkezik .
Megszorítások type_to: hivatkozás vagy mutató egy expression_fromtípus gyermekére.
A művelet generál-e kódot: igen. dynamic_cast
Logikai hibák lehetségesek, ha a művelet olyan argumentumot ad át, amelynek nincs típusa type_to, és nem ellenőrzi a mutató egyenlőségét (illetve ne kezelje a kivételt ). NULLstd::bad_cast
Művelet const_castCél: módosító(k) eltávolítása/beszerelése , és/vagy . Ezt gyakran arra használják, hogy megkerüljék egy program vagy könyvtár rossz architektúráját, a C-t dokkolja a C++-szal, információt adjon át általános mutatókon , hogy egyidejűleg írjon egy függvény const és nem const változatát [3] ( van egy bypass C++14 [3] -on keresztül ). constvolatilemutablevoid*decltype(auto)
Korlátozások expression_from: A kifejezésnek hivatkozást vagy mutatót kell visszaadnia.
Korlátozások type_to: a típusnak type_tomeg kell egyeznie a kifejezés típusával expression_fromegészen módosító(k) ig , és . constvolatilemutable
A művelet generál-e kódot: nem. const_cast
Logikai hibák forrásai: A program módosíthat egy megváltoztathatatlan objektumot. Néha ez szegmentációs hibához vezethet , néha pedig egy szubrutin nem számíthat arra , [3] hogy az olvasásra elérhető memória hirtelen megváltozott.
Vegyük például a dinamikus könyvtár kódját .
#include <karakterlánc> // karakterlánc névtér használata std ; névtér { string s = "Wikipédia" ; // Globális változó // Metódus string::c_str() const char * } típusú mutatót ad vissza typedef char * PChar ; void __declspec ( dllexport ) WINAPI SomeDllFunction ( PChar & rMessage ) { // char const * konvertálása char * -ra rMessage = const_cast < char * > ( s . c_str () ); }Amikor egy könyvtár betöltődik a folyamatmemóriába , új adatszegmenst hoz létre, amely globális változókat tartalmaz. A függvénykód a könyvtárban található, és meghívásakor egy mutatót ad vissza a globális osztályobjektum rejtett tagjára . A művelet a módosító eltávolítására szolgál . SomeDllFunction()stringconst_castconst
Művelet reinterpret_castHozzárendelés: Gépelési szójáték - Más (nem feltétlenül az adott típussal kompatibilis) típus hozzárendelése egy memóriahelyhez, a bitreprezentáció megőrzése mellett.
A kifejezés által visszaadott objektumot a expression_fromrendszer egy típusú objektumként kezeli type_to.
Korlátozások expression_from: A kifejezésnek sorszámú értéket kell visszaadnia (bármilyen egész, logikai érték vagy enum ), mutatót vagy hivatkozást. boolenum
Korlátozások type_to:
A művelet generál-e kódot: nem. reinterpret_cast
A logikai hibák forrásai. Előfordulhat , hogy a kifejezés által visszaadott objektum expression_fromnem típusú type_to. Ennek ellenőrzésére nincs mód, a programozó teljes felelősséget vállal az átalakítás helyességéért.
Vegye figyelembe a példákat.
// Igazat ad vissza, ha x véges. // Hamis értéket ad vissza, ha x szám ∞ vagy NaN. bool isfinite ( double const x ) { // konverzió double const -> uint64_t const & uint64_t const & y = reinterpret_cast < uint64_t const & > ( x ); return ( ( y & UINT64_C ( 0x7FF0000000000000 ) ) != UINT64_C ( 0x7FF0000000000000 ) ); } // egy ideiglenes érték címének megkísérlése long const & y = reinterpret_cast < long const & > ( x + 5.0 ); // hiba: az x + 5.0 kifejezés nem hivatkozás