Typové odlévání

Aktuální verze stránky ještě nebyla zkontrolována zkušenými přispěvateli a může se výrazně lišit od verze recenzované 21. srpna 2021; kontroly vyžadují 2 úpravy .

Typová konverze ( typizace , donucení ) - v informatice převod hodnoty jednoho typu na hodnotu jiného typu . 

Popis

Existují typy obsazení:

Explicitní přetypování specifikuje programátor v textu programu pomocí:

Implicitní přetypování provádí překladatel ( překladač nebo tlumočník ) podle pravidel popsaných v jazykové normě. Většina jazykových standardů zakazuje implicitní převody.

Ve slabě typovaných objektově orientovaných jazycích, jako je C++ , je mechanismus dědičnosti implementován přetypováním typu ukazatele na aktuální objekt do základní třídy (v typově bezpečných jazycích , jako je OCaml , koncept přetypování typu v podstatě chybí a přípustnost odkazování na komponentu podtypu je řízena typy mechanismu kontroly konzistence v době kompilace a přímý přístup zůstává ve strojovém kódu).

Implicitní typ casting

Implicitní přetypování v C/C++

K implicitnímu přetypování dochází v následujících případech [1] :

Například při provádění binární aritmetické operace jsou hodnoty operandů přetypovány na stejný typ. Při dědění jsou ukazatele odvozené třídy přetypovány na ukazatele základní třídy.

Zvažte příklad v jazyce C.

dvojité d ; // skutečný typ long l ; // typ celého čísla int i ; // celočíselný typ if ( d > i ) d = i ; if ( i > l ) l = i ; if ( d == l ) d *= 2 ;

Při provádění porovnávacích operací a při přiřazování jsou proměnné různých typů implicitně přetypovány na stejný typ.

Implicitní konverze mohou mít vedlejší účinky. Například při přetypování čísla reálného typu na celočíselný typ se zlomková část ořízne ( zaokrouhlování se neprovádí) [2] . Zpětný převod může snížit přesnost kvůli rozdílům v reprezentaci reálných a celých čísel. Například v proměnné typu ( IEEE 754 s jednoduchou přesností číslo s plovoucí desetinnou čárkou ) nemůžete uložit číslo 16 777 217 bez ztráty přesnosti, ale  můžete do proměnné typu 32bitové celé číslo. Kvůli ztrátě přesnosti mohou porovnávací operace stejného čísla reprezentovaného celočíselným a reálným typem (například a ) dávat falešné výsledky (čísla se nemusí rovnat). float intintfloat

#include <stdio.h> int main ( void ) { int i_value = 16777217 ; float f_value = 16777216.0 ; printf ( "Celé číslo je:%d \n " , i_hodnota ); printf ( "Plovák je: %f \n " , f_value ); printf ( "Jejich rovnost:%d \n " , i_hodnota == f_hodnota ); }

Výše uvedený kód vypíše následující, pokud je velikost  32 bitů a kompilátor podporuje standard IEEE 754 : int

Celé číslo je: 16777217 Plovák je: 16777216,000000 Jejich rovnost: 1

Explicitní obsazení

Typ casting v C

Pro explicitní přetypování je název typu uveden v závorkách před proměnnou nebo výrazem. Zvažte příklad.

int X ; int Y = 200 ; char C = 30 ; X = ( int ) C * 10 + Y ; // Proměnná C je přetypována na typ int

Pro vyhodnocení posledního výrazu kompilátor provede něco takového:

  • nejprve je proměnná typu znaku explicitně přetypována na celočíselný typ pomocí bitové přípony ;Ccharint
  • jsou vyhodnoceny operandy pro operaci násobení. Levý operand je typu . Pravý operand je konstanta a takové konstanty jsou standardně typu . Protože oba operandy operátoru " * " jsou typu , neprovádí se žádné implicitní přetypování. Výsledek násobení má také typ ;int10intintint
  • vyhodnotí se operandy operace sčítání. Levý operand — výsledek násobení má typ . Pravý operand je proměnná typu . Protože oba operandy operátoru " + " jsou typu , neexistuje žádné implicitní přetypování na společný typ. Výsledek sčítání je také typu ;intYintintint
  • provedení zadání. Levý operand je proměnná typu . Pravý operand, výsledek vyhodnocení výrazu zapsaného napravo od znaménka " = ", má také typ . Protože oba operandy operátoru " = " jsou stejného typu, nedochází k implicitnímu přetypování.Xintint

I tak jsou možné chyby. Typ může být buď podepsaný ( ) nebo nepodepsaný ( ); výsledek závisí na implementaci kompilátoru a toto chování je standardem povoleno. Hodnota nepodepsaného typu při převodu na podepsaný typ se může ukázat jako záporná kvůli implementaci strojových instrukcí na některých procesorech . Aby se předešlo nejednoznačnostem, doporučuje se explicitně specifikovat signaturu pro typ . charsigned charunsigned charcharintchar

Typ casting v C++

V C++ existuje pět explicitních operátorů konverze typů . První operace, závorky ( ), je podporována, aby byla zachována kompatibilita s C . Zbývající čtyři operace jsou zapsány jako (type_to)expression_from

xxx_cast < type_to >( expression_from )

Zvažte příklad.

y = static_cast < podepsaná zkratka > ( 65534 ); // proměnná y bude nastavena na -2

Těžkopádná klíčová slova jsou pro programátora připomínkou toho, že přetypování je plné problémů.

Operace static_cast

Účel: Platné obsazení.

Operace je podobná operaci závorek s jednou výjimkou: nepřetypuje ukazatele na nesouvisející typy (k tomu se používá operace ). static_castreinterpret_cast

Aplikace:

  • převod mezi numerickou a výčtou, včetně případů, kdy implicitní převod není možný ( ) nebo má za následek varování „Možná ztráta přesnosti“ ( );int enum classdouble float
  • přehazování ukazatelů na typ a naopak;void*
  • přetypování ukazatelů na odvozené typy na ukazatele na základní typy a naopak;
  • výběr jedné z několika přetížených funkcí ;
bool myLess ( const wchar_t * , const wchar_t * ); bool myLess ( const std :: wstring & , const std :: wstring & ); std :: vector < std :: wstring > seznam ; std :: sort ( seznam . begin (), seznam . konec (), static_cast < bool ( * )( const std :: wstring & , const std :: wstring & ) > ( myLess ));
  • explicitní volání konstruktoru s jedním argumentem nebo přetížená operace přetypování;
typ struktury { // konstruktor s jedním argumentem pro přetypování int do Type Type ( int ); // přetížená operace pro typ přetypování Type to type double operator double () const ; }; int main () { Typ x , y ; int i ; dvojité d ; // volání konstruktoru s jedním argumentem x = y + static_cast < Type > ( i ); // volání přetížené operace přetypování d = static_cast < double > ( x ); návrat 0 ; } konstruktor může mít více argumentů, ale musí jim být zadány výchozí hodnoty; typ struktury { // konstruktor s více argumenty pro přetypování do Type; // 2. a následující argumenty nastaveny na výchozí hodnoty ​​Type ( int , int = 10 , float = 0.0 ); };
  • přetypování typu v šablonách (překladač se již rozhoduje, jaké operace použít při specializaci šablony);
  • přetypování operandů ternární podmíněné operace " ?:" na stejný typ (hodnoty 2. a 3. operandu musí mít stejný typ);

Omezení na expression_from: ne.

Omezení na type_to: Musí existovat způsob, jak převést hodnotu výrazu expression_fromna typ type_to, using operator type_tonebo konstruktor.

Vytváří operace kód: Obecně ano (například volání přetíženého přetypování nebo operace konstruktoru). static_cast

Zdroje logických chyb: závisí na tom, co budete s operací dělat. Jsou možné přetečení, mimo rozsah a dokonce (pro převod ukazatelů) poškození paměti.

Příklady.

// Získejte procento zásahu. dvojité sklopné procento ( const int aHitCount , // počet zásahů const int aShotCount // počet výstřelů ) { if ( aShotCount == 0 ) return 0.0 ; // Casting to double se provádí za účelem provedení skutečného (neceločíselného) dělení return static_cast < double > ( aHitCount * 100 ) / static_cast < double > ( aShotCount ); } // následující řádky jsou ekvivalentní // pomocí operace static_cast string s = static_cast < string > ( "Ahoj!" ); // volání konstruktoru s jedním argumentem string s = string ( "Ahoj!" ); // pomocí operace v závorkách string s = ( string ) "Ahoj!" ; string s = static_cast < string > ( 5 ); // nezkompiluje, kompilátor nemůže najít vhodný konstruktor Operace dynamic_cast

Účel: seřazení hierarchie dědičnosti se zvláštním chováním, pokud objekt není požadovaného typu.

Operace získá informace o typu objektu expression_frompomocí RTTI . Pokud je typ type_tonebo jeho podtyp, přetypování se provede. V opačném případě:

Omezení na expression_from: Výraz musí být odkazem nebo ukazatelem na objekt, který má alespoň jednu virtuální funkci .

Omezení na type_to: odkaz nebo ukazatel na potomka expression_fromtypu.

Generuje operace kód: ano. dynamic_cast

Logické chyby jsou možné, pokud operace předá argument, který nemá typ type_toa nekontroluje rovnost ukazatele (respektive nezpracovává výjimku ). NULLstd::bad_cast

Operace const_cast

Účel: odstranění/instalace modifikátoru(ů) a /nebo . Často se to používá k překonání špatné architektury programu nebo knihovny, k dokování C s C++, k předávání informací přes generické ukazatele , k současnému psaní konstantní a nekonstové verze funkce [3] ( existuje bypass v C++14 [3] ). constvolatilemutablevoid*decltype(auto)

Omezení na expression_from: Výraz musí vracet odkaz nebo ukazatel.

Omezení na type_to: typ se musí shodovat s type_totypem výrazu expression_fromaž do modifikátorů a .constvolatilemutable

Generuje operace kód: no. const_cast

Zdroje logických chyb: Program může upravit neměnný objekt. Někdy to může vést k poruše segmentace , někdy podprogram nemůže očekávat [3] , že se paměť, kterou má k dispozici pro čtení, náhle změnila.

Zvažte například kód dynamické knihovny .

#include <řetězec> // řetězec pomocí jmenného prostoru std ; jmenný prostor { string s = "Wikipedie" ; // Globální proměnná // metoda string::c_str() vrací ukazatel typu const char * } typedef char * PChar ; void __declspec ( dllexport ) WINAPI SomeDllFunction ( PChar & rMessage ) { // převod char const * na char * rMessage = const_cast < char * > ( s . c_str () ); }

Když je knihovna načtena do paměti procesu , vytvoří se nový datový segment, který obsahuje globální proměnné. Kód funkce je umístěn v knihovně a při volání vrací ukazatel na skrytý člen objektu globální třídy . Operace se používá k odstranění modifikátoru . SomeDllFunction()stringconst_castconst

Operace reinterpret_cast

Přiřazení: Psací hříčka  - Přiřazení jiného typu (ne nutně kompatibilního s daným) do paměťového místa při zachování bitové reprezentace.

S objektem vráceným výrazem expression_fromse zachází jako s objektem typu type_to.

Omezení na expression_from: Výraz musí vracet hodnotu ordinálního typu (libovolné celé číslo, booleovské číslo nebo enum ), ukazatel nebo odkaz. boolenum

Omezení na type_to:

  • Pokud expression_fromvrátí hodnotu ordinálního typu nebo ukazatel, typ type_tomůže být ordinální typ nebo ukazatel.
  • Pokud expression_fromvrací odkaz, typ type_tomusí být odkaz.

Generuje operace kód: no. reinterpret_cast

Zdroje logických chyb. Objekt vrácený výrazem expression_fromnemusí být typu type_to. Nejde to nijak zkontrolovat, plnou zodpovědnost za správnost převodu přebírá programátor.

Zvažte příklady.

// Vrátí hodnotu true, pokud je x konečné. // Vrátí false, pokud číslo x je ∞ nebo NaN. bool isfinite ( double const x ) { // konverze double const -> uint64_t const & uint64_t const & y = reinterpret_cast < uint64_t const & > ( x ); return ( ( y & UINT64_C ( 0x7FF0000000000000 ) ) != UINT64_C ( 0x7FF0000000000000 ) ); } // pokus o získání adresy dočasné hodnoty long const & y = reinterpret_cast < long const & > ( x + 5.0 ); // chyba: výraz x + 5.0 není odkaz

Viz také

Poznámky

  1. cppreference.com. Implicitní konverze Archivováno 18. prosince 2014 na Wayback Machine .
  2. open-std.org ISO/IEC 9899:2018 C Programming Language Standard (C18) Archivováno 22. července 2020 na Wayback Machine 6.3.1.4 Real floating and integer.
  3. 1 2 3 C++ týdeník – Ep 283 – Přestaňte používat const_cast! - Youtube . Získáno 20. srpna 2021. Archivováno z originálu dne 20. srpna 2021.

Odkazy