Typ gjutning

Den aktuella versionen av sidan har ännu inte granskats av erfarna bidragsgivare och kan skilja sig väsentligt från versionen som granskades den 21 augusti 2021; kontroller kräver 2 redigeringar .

Typomvandling ( typcasting , tvång ) - inom datavetenskap , konvertering av ett värde av en typ till ett värde av en annan typ . 

Beskrivning

Det finns typavgjutningar:

Explicit rollbesättning anges av programmeraren i programtexten med hjälp av:

En implicit cast utförs av en översättare ( kompilator eller tolk ) enligt reglerna som beskrivs i språkstandarden. De flesta språkstandarder förbjuder implicita omvandlingar.

I svagt typade objektorienterade språk som C++ implementeras arvsmekanismen genom att casta pekarens typ till det aktuella objektet till basklassen (i typsäkra språk som OCaml , begreppet typcasting är i grunden frånvarande, och tillåtligheten av att hänvisa till undertypskomponenten styrs av mekanismtyperna för konsistenskontroll vid kompilering, och direktåtkomst kvarstår i maskinkoden).

Implicit typgjutning

Implicit typgjutning i C/C++

Implicit typgjutning förekommer i följande fall [1] :

Till exempel, när du utför en binär aritmetisk operation, casts värdena på operanderna till samma typ. I arv, härledda klasspekare gjuts till basklasspekare.

Tänk på ett exempel på C- språk .

dubbel d ; // riktig typ lång l ; // heltalstyp int i ; // heltalstyp if ( d > i ) d = i ; om ( i > l ) l = i ; om ( d == 1 ) d *= 2 ;

När man utför jämförelseoperationer och vid tilldelning, gjuts variabler av olika typer implicit till samma typ.

Implicita konverteringar kan ha biverkningar. Till exempel, när man gjuter ett antal verkliga typer till en heltalstyp, skärs bråkdelen av ( avrundning utförs inte) [2] . Den omvända omvandlingen kan minska noggrannheten på grund av skillnader i representationen av reella tal och heltal. Till exempel, i en typvariabel ( IEEE 754 single-precision flyttalnummer ), kan du inte lagra talet 16 777 217 utan förlust av precision, men  du kan i en 32-bitars heltalsvariabel. På grund av förlusten av precision kan jämförelseoperationer av samma tal representerade av heltal och reella typer (till exempel och ) ge falska resultat (tal kanske inte är lika). float intintfloat

#include <stdio.h> int main ( void ) { int i_värde = 16777217 ; float f_value = 16777216,0 ; printf ( "Heltalet är:%d \n " , i_värde ); printf ( "Flytet är: %f \n " , f_värde ); printf ( "Deras likhet:%d \n " , i_value == f_value ); }

Ovanstående kod matar ut följande om storleken  är 32 bitar och kompilatorn stöder IEEE 754- standarden : int

Heltalet är: 16777217 Flottören är: 16777216.000000 Deras jämlikhet: 1

Explicit rollbesättning

Skriv gjutning i C

För explicit typcasting anges typnamnet inom parentes före variabeln eller uttrycket. Tänk på ett exempel.

int X ; int Y = 200 ; kol C = 30 ; X = ( int ) C * 10 + Y ; // C-variabel cast till typ int

För att utvärdera det sista uttrycket gör kompilatorn ungefär så här:

  • först castas en teckentypsvariabel explicit till ett heltalstyp för bitförlängning ;Ccharint
  • operanderna för multiplikationsoperationen utvärderas. Den vänstra operanden är av typen . Den högra operanden är en konstant , och sådana konstanter är av typ som standard . Eftersom båda operanderna för " * "-operatorn är av typen utförs ingen implicit casting. Resultatet av multiplikation har också typ ;int10intintint
  • operanderna för additionsoperationen utvärderas. Vänster operand — resultatet av multiplikation har typen . Den högra operanden är en variabel av typen . Eftersom båda operanderna för " + "-operatorn är av typen , finns det ingen implicit cast till den vanliga typen. Resultatet av tillägget är också av typ ;intYintintint
  • uppdragsutförande. Den vänstra operanden är en variabel av typen . Den högra operanden, resultatet av att utvärdera uttrycket skrivet till höger om " = "-tecknet, har också typen . Eftersom båda operanderna för operatorn " = " är av samma typ, finns det ingen implicit casting.Xintint

Trots det är misstag möjliga. Typen kan antingen vara signerad ( ) eller osignerad ( ); resultatet beror på kompilatorns implementering och detta beteende tillåts av standarden. Värdet på en osignerad typ när den konverteras till en signerad typ kan visa sig vara negativt på grund av implementeringen av maskininstruktioner på vissa processorer . För att undvika oklarheter rekommenderas det att uttryckligen ange signering för typ . charsigned charunsigned charcharintchar

Skriv casting i C++

Det finns fem explicita typkonverteringsoperatorer i C++ . Den första operationen, parenteser ( ), stöds för att bibehålla kompatibilitet med C . De återstående fyra operationerna skrivs som (type_to)expression_from

xxx_cast < typ_to >( expression_from )

Tänk på ett exempel.

y = static_cast < signerad kort > ( 65534 ); // variabeln y sätts till -2

Besvärliga nyckelord är en påminnelse till programmeraren om att typgjutning är full av problem.

Operation static_cast

Syfte: Giltiga avgjutningar.

Operationen liknar parentesoperationen med ett undantag: den skickar inte pekare till orelaterade typer (operationen används för detta ). static_castreinterpret_cast

Ansökan:

  • konvertering mellan numerisk och enum, inklusive när implicit konvertering inte är möjlig ( ) eller resulterar i en "Möjlig förlust av precision"-varning ( );int enum classdouble float
  • gjuta pekare till typ och vice versa;void*
  • gjuta pekare till härledda typer till pekare till bastyper och vice versa;
  • val av en av flera överbelastade funktioner ;
bool myLess ( const wchar_t * , const wchar_t * ); bool myLess ( const std :: wstring & , const std :: wstring & ); std :: vektor < std :: wstring > lista ; std :: sort ( list . begin (), list . end (), static_cast < bool ( * )( const std :: wstring & , const std :: wstring & ) > ( myLess ));
  • ett explicit anrop till en enargumentkonstruktör eller en överbelastad gjutoperation;
strukturtyp { _ // konstruktor med ett argument för att casta int till Type Type ( int ); // överbelastad drift för gjutningstyp Typ till typ dubbeloperator dubbel () const ; }; int main () { Typ x , y ; int i ; dubbel d ; // anrop konstruktorn med ett argument x = y + static_cast < Typ > ( i ); // anropar en överbelastad cast-operation d = static_cast < double > ( x ); returnera 0 ; } konstruktorn kan ha fler argument, men de måste ges standardvärden; strukturtyp { _ // konstruktor med flera argument för att casta int till Type; // 2:a och efterföljande argument inställda på standardvärden Typ ( int , int = 10 , float = 0,0 ); };
  • typgjutning i mallar (kompilatorn bestämmer redan vilka operationer som ska användas när man specialiserar en mall);
  • gjutning av operanderna för den ternära villkorliga operationen " ?:" till samma typ (värdena för den 2:a och 3:e operanden måste ha samma typ);

Begränsningar på expression_from: nej.

Restriktioner på type_to: Det måste finnas ett sätt att konvertera uttryckets värde expression_fromtill typ type_to, med hjälp av operator type_toeller konstruktor.

Ger operationen kod: Generellt ja (till exempel anropar en överbelastad cast- eller konstruktoroperation). static_cast

Källor till logiska fel: beror på vad du ska göra med operationen. Översvämningar, utom räckvidd och till och med (för pekarkonverteringar) minneskorruption är möjliga.

Exempel.

// Få träffprocent. dubbel -tippercent ( const int aHitCount , // antal träffar konstant int aShotCount // antal skott ) { if ( aShotCount == 0 ) returnera 0,0 ; // Casting till dubbel görs för att utföra reell (icke-heltals) division return static_cast < double > ( aHitCount * 100 ) / static_cast < double > ( aShotCount ); } // följande rader är likvärdiga // använder operationssträngen static_cast s = static_cast < string > ( " Hej!" ); // anrop konstruktor med ett argument sträng s = sträng ( "Hej!" ); // med parentesens operation string s = ( string ) "Hej!" ; sträng s = static_cast < sträng > ( 5 ); // kompilerar inte, kompilatorn kan inte hitta en lämplig konstruktor Operation dynamic_cast

Syfte: kasta ner arvshierarkin, med speciellt beteende om objektet inte är av önskad typ.

Operationen erhåller information om typen av objekt expression_frommed hjälp av RTTI . Om typen är type_toeller en undertyp av den, utförs casten. Annat:

Restriktioner på expression_from: Uttrycket måste vara en referens eller pekare till ett objekt som har minst en virtuell funktion .

Begränsningar på type_to: en referens eller pekare till ett underordnat av en expression_fromtyp.

Genererar operationen en kod: ja. dynamic_cast

Logiska fel är möjliga om operationen skickar ett argument som inte har typ type_tooch inte kontrollerar pekaren för likhet (respektive hantera inte undantaget ). NULLstd::bad_cast

Operation const_cast

Syfte: borttagning/installation av modifierare och /eller . Ofta används detta för att komma runt den dåliga arkitekturen hos ett program eller bibliotek, för att docka C med C++, för att skicka information genom generiska pekare , för att samtidigt skriva en const- och icke-const-version av en funktion [3] ( det finns en bypass i C++14 [3] ). constvolatilemutablevoid*decltype(auto)

Restriktioner för expression_from: Uttrycket måste returnera en referens eller en pekare.

Begränsningar på type_to: typen type_tomåste matcha typen av uttrycket expression_fromupp till modifierare , och . constvolatilemutable

Genererar operationen en kod: nej. const_cast

Källor till logiska fel: Ett program kan modifiera ett oföränderligt objekt. Ibland kan detta leda till ett segmenteringsfel , ibland kan en subrutin inte förvänta sig [3] att minnet som den har gjort tillgängligt för läsning plötsligt har förändrats.

Tänk till exempel på koden för det dynamiska biblioteket .

#inkludera <sträng> // sträng använder namnutrymme std ; namnutrymme { string s = "Wikipedia" ; // Global variabel // method string::c_str() returnerar en pekare av typen const char * } typedef char * PChar ; void __declspec ( dllexport ) WINAPI SomeDllFunction ( PChar & rMessage ) { // konvertera char const * till char * rMessage = const_cast < char * > ( s . c_str () ); }

När ett bibliotek läses in i processminnet skapar det ett nytt datasegment som innehåller globala variabler. Funktionskoden finns i biblioteket och, när den anropas, returnerar den en pekare till en dold medlem av det globala klassobjektet . Operationen används för att ta bort modifieraren . SomeDllFunction()stringconst_castconst

Operation reinterpret_cast

Tilldelning: Skriva ordlek  - Tilldela en annan typ (inte nödvändigtvis kompatibel med den givna) till en minnesplats samtidigt som bitrepresentationen bevaras.

Objektet som returneras av uttrycket expression_frombehandlas som ett objekt av typen type_to.

Restriktioner på expression_from: Uttrycket måste returnera ett värde av en ordningstyp (valfritt heltal, boolean eller enum ), en pekare eller en referens. boolenum

Begränsningar på type_to:

  • Om den expression_fromreturnerar ett ordningstypvärde eller en pekare kan typen type_tovara en ordningstyp eller en pekare.
  • Om den expression_fromreturnerar en referens måste typen type_tovara en referens.

Genererar operationen en kod: nej. reinterpret_cast

Källor till logiska fel. Objektet som returneras av uttrycket expression_fromkanske inte är av typen type_to. Det finns inget sätt att kontrollera detta, programmeraren tar fullt ansvar för att konverteringen är korrekt.

Tänk på exempel.

// Returnerar sant om x är ändligt. // Returnerar falskt om nummer x är ∞ eller NaN. bool isfinite ( dubbelkonst x ) _ { // conversion double const -> uint64_t const & uint64_t const & y = reinterpret_cast < uint64_t const & > ( x ); return ( ( y & UINT64_C ( 0x7FF00000000000000 ) ) != UINT64_C ( 0x7FF0000000000000 ) ); } // försök att få adressen till ett temporärt värde long const & y = reinterpret_cast < long const & > ( x + 5.0 ); // fel: uttryck x + 5.0 är inte en referens

Se även

Anteckningar

  1. cppreference.com. Implicita konverteringar Arkiverade 18 december 2014 på Wayback Machine .
  2. open-std.org ISO/IEC 9899:2018 C Programming Language Standard (C18) Arkiverad 22 juli 2020 på Wayback Machine 6.3.1.4 Verkligt flytande och heltal.
  3. 1 2 3 C++ Weekly - Ep 283 - Sluta använda const_cast! - Youtube . Hämtad 20 augusti 2021. Arkiverad från originalet 20 augusti 2021.

Länkar