Převod typu - Type conversion
![]() | Tento článek má několik problémů. Prosím pomozte vylepši to nebo diskutovat o těchto problémech na internetu diskusní stránka. (Zjistěte, jak a kdy tyto zprávy ze šablony odebrat) (Zjistěte, jak a kdy odstranit tuto zprávu šablony)
|
v počítačová věda, převod typu,[1][2] odlévání typu,[1][3] nátlak typu,[3][3] a žonglování typu[4][5] jsou různé způsoby, jak změnit výraz od jednoho datový typ jinému. Příkladem může být převod z celé číslo hodnota do a plovoucí bod hodnota nebo její textové vyjádření jako a tětiva a naopak. Převody typu mohou využívat určité funkce hierarchie typů nebo reprezentace dat. Dva důležité aspekty převodu typu jsou, zda k němu dojde implicitně (automaticky) nebo výslovně[1][6], a zda je podkladová reprezentace dat převedena z jedné reprezentace na jinou, nebo je daná reprezentace pouze reinterpretováno jako reprezentace jiného datového typu.[6][7] Obecně obojí primitivní a složené datové typy lze převést.
Každý programovací jazyk má svá vlastní pravidla, jak lze typy převádět. Jazyky s silné psaní obvykle dělají malou implicitní konverzi a odrazují od reinterpretace reprezentací, zatímco jazyky s slabé psaní provádět mnoho implicitních převodů mezi datovými typy. Slabý jazyk psaní často umožňuje vynucení překladač libovolně interpretovat datovou položku jako jinou reprezentaci - může to být zjevná chyba programování nebo technická metoda přímého řešení základního hardwaru.
Ve většině jazyků slovo donucování se používá k označení implicitní konverze, ať už během kompilace nebo během doba běhu. Například ve výrazu mísícím celé číslo a čísla s plovoucí desetinnou čárkou (například 5 + 0,1) kompilátor automaticky převede celočíselnou reprezentaci na reprezentaci s plovoucí desetinnou čárkou, aby se neztratily zlomky. Explicitní převody typů jsou buď indikovány zápisem dalšího kódu (např. Přidáním identifikátorů typu nebo voláním integrovaného typu) rutiny ) nebo kódováním převodních rutin, které má kompilátor použít, pokud by se jinak zastavil s neshodou typu.
Ve většině ALGOL -jako jazyky, jako např Pascal, Modula-2, Ada a Delphi, konverze a odlévání jsou zřetelně odlišné pojmy. V těchto jazycích konverze označuje buď implicitně, nebo explicitně změnu hodnoty z jednoho formátu úložiště datového typu na jiný, např. 16bitové celé číslo na 32bitové celé číslo. Potřeby úložiště se mohou v důsledku převodu změnit, včetně možné ztráty přesnosti nebo zkrácení. Slovo obsazení, na druhé straně, odkazuje na výslovnou změnu výklad z bitový vzor představující hodnotu z jednoho typu do druhého. Například 32 sousedících bitů lze považovat za pole 32 booleanů, 4bajtový řetězec, nepodepsané 32bitové celé číslo nebo hodnotu plovoucí desetinné čárky s jedinou přesností IEEE. Protože uložené bity se nikdy nezmění, programátor musí znát podrobnosti na nízké úrovni, jako je formát reprezentace, pořadí bajtů a potřeby zarovnání, aby mohl smysluplně obsazení.
V rodině jazyků C a ALGOL 68, slovo obsazení obvykle se odkazuje na explicitní převod typu (na rozdíl od implicitního převodu), což způsobuje určité nejasnosti ohledně toho, zda se jedná o re-interpretaci bitového vzoru nebo o převod skutečné reprezentace dat. Důležitější je množství způsobů a pravidel, která se vztahují na to, jaký datový typ (nebo třída) je umístěn ukazatelem a jak může být ukazatel upraven kompilátorem v případech, jako je dědičnost objektu (třídy).
Porovnání jazyků
C-jako jazyky
Implicitní převod typu
Implicitní převod typu, známý také jako donucování, je automatická konverze typu překladač. Nějaký programovací jazyky umožnit překladatelům poskytnout nátlak; ostatní to vyžadují.
Ve výrazu smíšeného typu data jednoho nebo více podtypy může být převedeny podle potřeby na supertyp runtime aby program běžel správně. Například následující je legální Jazyk C. kód:
dvojnásobek d;dlouho l;int i;-li (d > i) d = i;-li (i > l) l = i;-li (d == l) d *= 2;
Ačkoli d, l, a i patří do různých datových typů, budou automaticky převedeny na stejné datové typy při každém provedení srovnání nebo přiřazení. Toto chování je třeba používat opatrně, protože nezamýšlené důsledky může vzniknout. Při převodu reprezentací z plovoucí desetinné čárky na celé číslo může dojít ke ztrátě dat, protože zlomkové komponenty hodnot s plovoucí desetinnou čárkou budou zkráceny (zaokrouhleno na nulu). Naopak, přesnost může být ztracena při převodu reprezentací z celého čísla na plovoucí desetinnou čárku, protože typ s plovoucí desetinnou čárkou nemusí být schopen přesně reprezentovat celočíselný typ. Například, plovák
může být IEEE 754 jediný přesný typ, který nemůže přesně představovat celé číslo 16777217, zatímco 32bitový celočíselný typ může. To může vést k neintuitivnímu chování, jak ukazuje následující kód:
#zahrnout <stdio.h>int hlavní(prázdnota){ int i_value = 16777217; plovák f_value = 16777216.0; printf("Celé číslo je:% d n", i_value); printf("Plovák je:% f n", f_value); printf("Jejich rovnost:% d n", i_value == f_value);}
Na kompilátorech, které implementují plováky jako jedinou přesnost IEEE, a ints jako alespoň 32 bitů, tento kód poskytne tento zvláštní výtisk:
Celé číslo je: 16777217 Float je: 16777216.000000 Jejich rovnost: 1
Všimněte si, že 1 představuje rovnost v posledním řádku výše. Toto zvláštní chování je způsobeno implicitním převodem i_value
plavat při srovnání s f_value
. Převod způsobí ztrátu přesnosti, díky čemuž jsou hodnoty před porovnáním stejné.
Důležité jídlo:
plovák
naint
příčiny zkrácení tj. odstranění zlomkové části.dvojnásobek
naplovák
způsobí zaokrouhlení číslice.dlouho
naint
způsobí pokles nadbytečných bitů vyššího řádu.
Zadejte propagaci
Jedním zvláštním případem převodu implicitního typu je podpora typu, kde kompilátor automaticky rozšiřuje binární reprezentaci objektů celočíselných nebo s plovoucí desetinnou čárkou. Promo akce se běžně používají u typů menších, než je nativní typ cílové platformy aritmetická logická jednotka (ALU), před aritmetickými a logickými operacemi, aby tyto operace byly možné nebo efektivnější, pokud ALU může pracovat s více než jedním typem. C a C ++ provádějí takovou propagaci pro objekty typu boolean, character, wide character, enumeration a short integer types which are promoted to int, and for objects of type float, which are promoted to double. Na rozdíl od některých jiných převodů typů propagace nikdy neztratí přesnost ani nezmění hodnotu uloženou v objektu.
v Jáva:
int X = 3;dvojnásobek y = 3.5;Systém.ven.tisk(X + y); // Výstup bude 6,5
Explicitní převod typu
Explicitní převod typu je převod typu, který je explicitně definován v rámci programu (namísto provedení kompilátorem pro převod implicitního typu). Je definován uživatelem v programu.
dvojnásobek da = 3.3;dvojnásobek db = 3.3;dvojnásobek DC = 3.4;int výsledek = (int)da + (int)db + (int)DC; // výsledek == 9// pokud by byla použita implicitní konverze (jako u „result = da + db + dc“), výsledek by byl roven 10
Existuje několik druhů explicitní konverze.
- kontrolovány
- Před provedením převodu se provede kontrola za běhu, aby se zjistilo, zda typ cíle může obsahovat zdrojovou hodnotu. Pokud ne, vyvolá se chybový stav.
- nezaškrtnuto
- Není provedena žádná kontrola. Pokud typ cíle nemůže obsahovat zdrojovou hodnotu, výsledek je nedefinovaný.
- bitový vzor
- Surová bitová reprezentace zdroje je zkopírována doslovně a je znovu interpretována podle typu cíle. Toho lze dosáhnout také prostřednictvím aliasing.
v objektově orientované programování jazyky, mohou být také objekty skleslý : je odkaz na základní třídu přetypován na jednu z jejích odvozených tříd.
C # a C ++
v C#, převod typu lze provést bezpečným nebo nebezpečným (tj. C) podobným způsobem, tzv. první zaškrtnutý typ obsazení.[8]
Zvíře zvíře = Nový Kočka();Buldok b = (Buldok) zvíře; // if (animal is Bulldog), stat.type (animal) is Bulldog, else an exceptionb = zvíře tak jako Buldok; // if (animal is Bulldog), b = (Bulldog) animal, else b = nullzvíře = nula;b = zvíře tak jako Buldok; // b == null
v C ++ podobného efektu lze dosáhnout použitím Syntaxe obsazení ve stylu C ++.
Zvíře* zvíře = Nový Kočka;Buldok* b = static_cast<Buldok*>(zvíře); // kompiluje se pouze v případě, že buď zvíře, nebo buldok je odvozen od druhého (nebo stejného)b = dynamic_cast<Buldok*>(zvíře); // if (animal is Bulldog), b = (Bulldog *) animal, else b = nullptrBuldok& br = static_cast<Buldok&>(*zvíře); // stejné jako výše, ale výjimka bude vyvolána, pokud se má vrátit nullptr // to není vidět v kódu, kde je zabráněno zpracování výjimekzvíře = nullptr;b = dynamic_cast<Buldok*>(zvíře); // b == nullptrvymazat zvíře; // vždy zdroje zdarma
Eiffelova
v Eiffelova pojem převodu typu je integrován do pravidel typového systému. Pravidlo přiřazení říká, že úkol, například:
X := y
je platný právě tehdy, pokud je typ jeho zdrojového výrazu, y
v tomto případě je kompatibilní s typ jeho cílové entity, X
v tomto případě. V tomto pravidle kompatibilní s znamená, že buď typ zdrojového výrazu vyhovuje nebo převádí na cíle. Shoda typů je definována známými pravidly pro polymorfismus v objektově orientovaném programování. Například v úkolu výše typ y
odpovídá typu X
pokud třída, na které y
je založen je potomkem toho, na kterém X
je založen.
Definice převodu typu v Eiffelově síti
Konkrétně akce převodu typu v Eiffelu převádí na a konvertuje z jsou definovány jako:
Typ založený na CU třídy převádí na typ T založený na třídě CT (a T konvertuje z U) pokud buď
- CT má a postup převodu použití U jako typu převodu, nebo
- UK má konverzní dotaz výpis T jako typ převodu
Příklad
Eiffel je plně kompatibilní Jazyk pro Microsoft .NET Framework. Před vývojem .NET měl Eiffel již rozsáhlé knihovny tříd. Použití knihoven typů .NET, zejména u běžně používaných typů, jako jsou řetězce, představuje problém s převodem. Stávající software Eiffel používá třídy řetězců (např STRING_8
) z knihoven Eiffel, ale software Eiffel napsaný pro .NET musí používat třídu řetězců .NET (System.String
) v mnoha případech, například při volání metod .NET, které očekávají, že položky typu .NET budou předány jako argumenty. Takže převod těchto typů tam a zpět musí být co nejplynulejší.
můj_řetězec: STRING_8 - Nativní Eiffelova struna my_system_string: SYSTEM_STRING - Nativní řetězec .NET ... můj_řetězec := my_system_string
Ve výše uvedeném kódu jsou deklarovány dva řetězce, jeden z každého jiného typu (SYSTEM_STRING
je Eiffel vyhovující alias pro System.String). Protože System.String
neodpovídá STRING_8
, pak výše uvedený úkol je platný, pouze pokud System.String
převádí na STRING_8
.
Eiffelova třída STRING_8
má postup převodu make_from_cil
pro objekty typu System.String
. Konverzní procedury jsou také vždy označovány jako procedury vytváření (podobné konstruktorům). Následuje výňatek z STRING_8
třída:
třída STRING_8 ... vytvořit make_from_cil ... konvertovat make_from_cil ({SYSTEM_STRING}) ...
Přítomnost postupu převodu umožňuje přiřazení:
můj_řetězec := my_system_string
sémanticky ekvivalentní:
vytvořit můj_řetězec.make_from_cil (my_system_string)
ve kterém můj_řetězec
je konstruován jako nový objekt typu STRING_8
s obsahem rovnocenným obsahu z my_system_string
.
Zpracování úkolu s obráceným původním zdrojem a cílem:
my_system_string := můj_řetězec
třída STRING_8
také obsahuje dotaz na převod to_cil
který bude vyrábět System.String
z instance STRING_8
.
třída STRING_8 ... vytvořit make_from_cil ... konvertovat make_from_cil ({SYSTEM_STRING}) to_cil: {SYSTEM_STRING} ...
Zadání:
my_system_string := můj_řetězec
pak se stane ekvivalentem:
my_system_string := můj_řetězec.to_cil
V Eiffelu je nastavení převodu typu zahrnuto v kódu třídy, ale zdá se, že se to děje stejně automaticky jako explicitní převod typu v kódu klienta. Zahrnuje nejen přiřazení, ale i další typy příloh, například substituci argumentů (parametrů).
Rez
Rez neposkytuje žádnou implicitní konverzi typu (nátlak) mezi primitivními typy. Explicitní převod typu (casting) lze ale provést pomocí tak jako
klíčové slovo.[9]
tisk!(„1000 jako u16 je: {}“,1000tak jakou16);
Bezpečnostní problémy
v hackování, typecasting je zneužití převodu typu k dočasné změně a proměnná Datový typ z toho, jak byl původně definován.[10] To poskytuje hackerům příležitosti, protože při převodu typu poté, co se proměnná stane „typickým“, aby se stal jiným datovým typem, bude kompilátor považovat tuto hacknutou proměnnou za nový datový typ pro tuto konkrétní operaci.[11]
Viz také
Reference
- ^ A b C Počítačová věda S. Chanda. 2008. str. 81–83. ISBN 8121929849.
- ^ Programovací jazyky - design a konstrukce. 2013. s. 35. ISBN 9381159416.
- ^ A b C Reilly, Edwin (2004). Stručná encyklopedie informatiky. str.82, 110. ISBN 0470090952.
- ^ Fenton, Steve (2017). Pro TypeScript: Vývoj JavaScriptu v měřítku aplikace. str. xxiii. ISBN 1484232496.
- ^ „PHP: Type Juggling - Manual“. php.net. Citováno 27. ledna 2019.
- ^ A b Olsson, Mikael (2013). Rychlá reference syntaxe C ++. 87–89. ISBN 143026277X.
- ^ Výpočetní inteligence: Metodický úvod. p. 269. ISBN 1447172965.
- ^ Mössenböck, Hanspeter (25. března 2002). „Advanced C #: Checked Type Casts“ (PDF). Institut für Systemsoftware, Johannes Kepler Universität Linz, Fachbereich Informatik. p. 5. Citováno 4. srpna 2011. na C # výuka
- ^ „Casting - Rust příkladem“. doc.rust-lang.org.
- ^ Jon Erickson Hacking, 2. vydání: The Art of Exploitation 2008 1593271441 p51 "Typecasting je jednoduše způsob, jak dočasně změnit datový typ proměnné, a to navzdory tomu, jak byla původně definována. Když je proměnná obsazena do jiného typu, je kompilátoru v zásadě řečeno, aby s touto proměnnou zacházel, jako by to byla nová data type, ale pouze pro tuto operaci. Syntaxe pro typecasting je následující: (typecast_data_type) proměnná ... "
- ^ Arpita Gopal Zvětšení C. 2009 8120338618 str.59 „Z výše uvedeného je zřejmé, že použití psaní typu je vytvořit proměnnou jednoho typu, chovat se jako jiný typ pro jednu operaci. Takže pomocí této schopnosti psaní je možné vytvářet znaky ASCII zadáním celého čísla do jeho ... "