C ++

Štandardné konverzie v C ++

Štandardné konverzie v C ++
V C ++ existujú dva typy entít, základné typy a zložené typy. Základné typy sú skalárne typy. Zložené typy sú zvyšok typov entít. Konverzia sa môže uskutočniť z jedného typu entity na iný vhodný typ. Zvážte nasledujúci program:

#include
#include
pomocou namespace std;
int main ()

int rt1 = sqrt (5);
int rt2 = sqrt (8);
cout<návrat 0;

Výstup je 2, 2, čo znamená, že program vrátil druhú odmocninu z 5 ako 2 a druhú odmocninu z 8 tiež ako 2. Prvé dva výroky v hlavný() funkcia umocnila odpovede na druhú odmocninu z 5 a na druhú odmocninu z 8. Tento článok sa nezaoberá podlahami alebo stropom v jazyku C++. Tento článok skôr pojednáva o prevode jedného typu C ++ na iný vhodný typ C ++; označujúce akúkoľvek aproximáciu dosiahnutej hodnoty, straty presnosti alebo pridaného alebo odstráneného obmedzenia. Základné znalosti jazyka C ++ sú nevyhnutnou podmienkou na pochopenie tohto článku.

Obsah článku

  • Integrované konverzie
  • Konverzie s pohyblivou desatinnou čiarkou
  • Plávajúce integrálne konverzie
  • Poradie konverzií celých čísel
  • Integrované propagácie
  • Obvyklé aritmetické konverzie
  • Podpora pohyblivých bodov
  • Konverzie ukazovateľa
  • Konverzie funkcie na ukazovateľ
  • Booleovské konverzie
  • Lvalue, prvalue a xvalue
  • Xvalue
  • Konverzie z hodnoty na r
  • Konverzie z poľa na ukazovateľ
  • Konverzie funkcie na ukazovateľ
  • Dočasné konverzie materializácie
  • Konverzie kvalifikácie
  • Záver

Integrované konverzie

Integrálne prepočty sú celočíselné prepočty. Nepodpísané celé čísla zahŕňajú „nepodpísaný znak“, „nepodpísaný krátky int“, „nepodpísaný int“, „nepodpísaný dlhý int“ a „nepodpísaný dlhý dlhý int.„Zodpovedajúce celé čísla so znamienkom zahŕňajú„ podpísané znaky “,„ krátke int “,„ int “,„ dlhé int “a„ dlhé dlhé int “.„Každý typ int by mal byť uchovávaný v toľkých bajtoch ako jeho predchodca. Pre väčšinu systémov možno jeden typ entity bez problémov previesť na zodpovedajúci typ. Problém nastáva pri prevode z väčšieho rozsahu na menší rozsah alebo pri prevode podpísaného čísla na zodpovedajúce nepodpísané číslo.

Každý kompilátor má maximálnu hodnotu, ktorú môže mať pre short int. Ak je krátkemu int priradené číslo vyššie ako toto maximum, určené pre int, kompilátor použije nejaký algoritmus a vráti číslo v rozsahu krátkeho int. Ak má programátor šťastie, kompilátor upozorní na problémy s použitím nevhodnej konverzie. To isté vysvetlenie platí pre konverzie iných typov int.

Používateľ by mal v dokumentácii kompilátora zistiť limitné hodnoty pre každý typ entity.

Ak sa má záporné podpísané číslo krátkeho int previesť na nepodpísané krátke int číslo, kompilátor použije nejaký algoritmus a vráti kladné číslo v rozsahu nepodpísaného krátkeho int. Tomuto druhu premeny by sa malo zabrániť. To isté vysvetlenie platí pre konverzie iných typov int.

Akékoľvek celé číslo, okrem 0, je možné previesť na boolovskú hodnotu true. 0 sa prevedie na boolovskú hodnotu false. Ilustruje to nasledujúci kód:

int a = -27647;
float b = 2.5;
int c = 0;
bool a1 = a;
bool b1 = b;
bool c1 = c;
cout<cout<cout<Výstup je:

1 za pravdu
1 za pravdu
0 pre nepravdivé

Konverzie s pohyblivou desatinnou čiarkou

Typy s pohyblivou rádovou čiarkou zahŕňajú „plavák“, „dvojitý“ a „dlhý dvojitý“.„Typy s pohyblivou rádovou čiarkou nie sú zoskupené do znakov a znakov, ako sú celé čísla. Každý typ môže mať podpísané alebo nepodpísané číslo. Typ s pohyblivou rádovou čiarkou by mal mať minimálne rovnakú presnosť ako jeho predchodca. To znamená, že „dlhý dvojitý“ by mal mať rovnakú alebo väčšiu presnosť ako „dvojitý“ a „dvojitý“ by mal mať rovnakú alebo väčšiu presnosť ako „float“.“

Pamätajte, že rozsah typu s pohyblivou rádovou čiarkou nie je spojitý; skôr je to po malých krokoch. Čím väčšia je presnosť typu, tým menšie sú kroky, a tým väčší je počet bajtov na uloženie čísla. Takže keď sa číslo s pohyblivou rádovou čiarkou prevádza z typu s nižšou presnosťou na typ s vyššou presnosťou, musí programátor akceptovať nesprávne zvýšenie presnosti a možné zvýšenie počtu bajtov pre ukladanie čísel. Keď sa číslo s pohyblivou rádovou čiarkou prevádza z typu s vyššou presnosťou na typ s nižšou presnosťou, musí programátor akceptovať stratu presnosti. Ak je potrebné znížiť počet bajtov pre ukladanie čísel, kompilátor použije určitý algoritmus a vráti číslo ako náhradu (čo pravdepodobne programátor nechce). Pamätajte tiež na problémy mimo dosah.

Plávajúce integrálne konverzie

Číslo s pohyblivou rádovou čiarkou sa prevedie na celé číslo skrátením zlomkovej časti. Ilustruje to nasledujúci kód:

plavák f = 56.953;
int i = f;
cout<Výstup je 56. Rozsahy pre float a integer musia byť kompatibilné.

Keď sa celé číslo prevedie na float, hodnota zobrazená ako float je rovnaká, ako bola zadaná ako celé číslo. Avšak floatovým ekvivalentom môže byť presná hodnota alebo môže mať nepatrný zlomkový rozdiel, ktorý sa nezobrazí. Dôvod zlomkového rozdielu spočíva v tom, že čísla s pohyblivou rádovou čiarkou sú v počítači zastúpené v malých zlomkových krokoch, a teda predstavovať celé číslo presne by bola náhoda. Aj keď je celé číslo zobrazené ako plavák rovnaké, ako bolo zadané, môže ísť o približnú hodnotu toho, čo je uložené.

Poradie konverzií celých čísel

Akýkoľvek celočíselný typ má poradie, ktoré mu bolo dané. Toto poradie pomáha pri konverzii. Poradie je relatívne; poradia nie sú na pevných úrovniach. Okrem znakov char a podpísaných znakov žiadne dve podpísané celé čísla nemajú rovnaké hodnotenie (za predpokladu, že znak je podpísaný). Celé typy bez znamienka majú rovnaké hodnotenie ako ich zodpovedajúce celočíselné typy so znamienkom. Poradie je nasledovné:

  • Za predpokladu, že znak je podpísaný, potom znak a znak majú rovnaké hodnotenie.
  • Poradie celočíselného typu so znamienkom je väčšie ako poradie celočíselného typu so znamienkom a menším počtom bajtov úložiska. Takže poradie podpísaného dlhého dlhého int je väčšie ako poradie podpísaného dlhého int, čo je väčšie ako poradie podpísaného int, čo je väčšie ako poradie podpísaného long int, ktoré je väčšie ako poradie podpísaného char.
  • Poradie ľubovoľného typu celého čísla bez znamienka sa rovná hodnosti zodpovedajúceho typu celého čísla so znamienkom.
  • Poradie nepodpísaného znaku sa rovná hodnosti podpísaného znaku.
  • bool má najmenšiu hodnosť; jeho hodnotenie je menšie ako hodnotenie podpísaného znaku.
  • char16_t má rovnaké poradie ako short int. char32_t má rovnaké poradie ako int. Pre kompilátor g ++ má wchar_t rovnaké hodnotenie ako int.

Integrované propagácie

Integral Promotions je Integer Promotions. Nie je dôvod, prečo celé číslo s menším počtom bajtov nemôže byť reprezentované celým číslom s väčším počtom bajtov. Program Integer Promotions sa zaoberá všetkým nasledujúcim:

  • Podpísaný krátky int (dva bajty) je možné previesť na podpísaný int (štyri bajty). Nepodpísaný krátky int (dva bajty) je možné previesť na nepodpísaný int (štyri bajty). Poznámka: prevod krátkeho int na dlhý int alebo long long int vedie k mrhaniu bajtov ukladacieho priestoru (umiestnenie objektu) a mrhaniu pamäte. Bool, char16_t, char32_t a wchar_t sú z tejto propagácie vyňaté (s kompilátorom g ++ majú char32_t a wchar_t rovnaký počet bajtov).
  • Pomocou kompilátora g ++ je možné typ char16_t konvertovať na typ int podpísaného alebo typu int bez znamienka; typ char32_t je možné previesť na podpísaný typ int alebo nepodpísaný typ int; a typ wchar_t možno previesť na podpísaný alebo nepodpísaný typ int.
  • Typ bool je možné previesť na typ int. V takom prípade sa true stane 1 (štyri bajty) a false 0 (štyri bajty). Int môže byť podpísaný alebo podpísaný.
  • Celočíselná propagácia existuje aj pre nespracovaný typ výčtu - pozri ďalej.

Obvyklé aritmetické konverzie

Zvážte nasledujúci kód:

plavák f = 2.5;
int i = f;
cout<Kód sa kompiluje bez udania varovania alebo chyby a poskytuje výstup z 2, čo pravdepodobne nie je to, čo sa očakávalo. = je binárny operátor, pretože trvá ľavý a pravý operand. Zvážte nasledujúci kód:

int i1 = 7;
int i2 = 2;
float flt = i1 / i2;
cout<Výstup je 3, ale toto je zle; malo to byť 3.5. Operátor divízie / je tiež binárny operátor.

C ++ má bežné aritmetické prevody, ktoré musí programátor poznať, aby sa vyhli chybám v kódovaní. Zvyčajné aritmetické prevody na binárne operátory sú nasledujúce:

  • Ak je jeden z operandov typu „dlhý dvojitý“, druhý bude prevedený na dlhý dvojitý.
  • Inak, ak je jeden operand dvojnásobný, druhý bude prevedený na dvojnásobok.
  • Inak, ak je jeden operand float, druhý bude prevedený na float. Vo vyššie uvedenom kóde je výsledok i1 / i2 oficiálne 2; preto je flt 2. Výsledok binárneho súboru, /, sa použije ako pravý operand na binárny operátor, =. Takže konečná hodnota 2 je float (nie int).

INÁ, PODPORA INTEGRÁTORA, BY MALA BYŤ TAKTO:

  • Ak sú oba operandy rovnakého typu, potom sa už ďalšia konverzia nekoná.
  • Inak, ak sú oba operandy celočíselné typy so znamienkom alebo oba sú celé typy bez znamienka, potom sa operand typu s nižším celočíselným hodnotením prevedie na typ operandu s vyšším hodnotením.
  • Inak, ak je jeden operand podpísaný a druhý nepodpísaný, a ak je typ nepodpísaného operandu väčší alebo rovný hodnosti typu podpísaného operandu, a ak je hodnota podpísaného operandu väčšia alebo rovná nule, potom podpísaný operand bude prevedený na typ nepodpísaného operandu (s ohľadom na rozsah). Ak je podpísaný operand záporný, potom kompilátor použije algoritmus a vráti číslo, ktoré nemusí byť pre programátora prijateľné.
  • Inak, ak je jeden operand celočíselný typ so znamienkom a druhý je celočíselný typ bez znamienka a ak všetky možné hodnoty typu operandu s celočíselným typom bez znamienka môžu byť zastúpené typom so znamienkom typu celé číslo, potom bude typ bez znamienka celé číslo. sa prevedú na typ operandu typu celé číslo so znamienkom.
  • Inak by sa dva operandy (napríklad char a bool) konvertovali na celočíselný typ bez znamienka.

Podpora pohyblivých bodov

Typy s pohyblivou rádovou čiarkou zahŕňajú „plavák“, „dvojitý“ a „dlhý dvojitý“.„Typ s pohyblivou rádovou čiarkou by mal mať minimálne rovnakú presnosť ako jeho predchodca. Propagácia s pohyblivou rádovou čiarkou umožňuje prevod z float na double alebo z double na long double.

Konverzie ukazovateľa

Ukazovateľ jedného typu objektu nemožno priradiť k ukazovateľu iného typu objektu. Nasledujúci kód sa nebude kompilovať:

int id = 6;
int * intPtr = &id;
float idf = 2.5;
float * floatPtr = &idf;
intPtr = floatPtr; // chyba tu

Nulový ukazovateľ je ukazovateľ, ktorého hodnota adresy je nula. Nulový ukazovateľ jedného typu objektu nemožno priradiť k nulovému ukazovateľu iného typu objektu. Nasledujúci kód sa nebude kompilovať:

int id = 6;
int * intPtr = &id;
intPtr = 0;
float idf = 2.5;
float * floatPtr = &idf;
floatPtr = 0;
intPtr = floatPtr; // chyba tu

Konštantu nulového ukazovateľa jedného typu objektu nie je možné priradiť k konštante nulového ukazovateľa iného typu objektu. Nasledujúci kód sa nebude kompilovať:

int id = 6;
int * intPtr = &id;
int * const intPC = 0;
float idf = 2.5;
float * floatPtr = &idf;
float * const floatPC = 0;
intPC = floatPC; // chyba tu

Nulovému ukazovateľu možno pre jeho typ priradiť inú hodnotu adresy. Ilustruje to nasledujúci kód:

float idf = 2.5;
float * floatPtr = 0;
floatPtr = &idf;
cout<<*floatPtr<<'\n';

Výstup je 2.5.

Podľa očakávania konštante nulového ukazovateľa nemožno priradiť žiadnu hodnotu adresy svojho typu. Nasledujúci kód sa nebude kompilovať:

float idf = 2.5;
float * const floatPC = 0;
floatPC = &idf; // chyba tu

Konštante nulového ukazovateľa však možno priradiť bežný ukazovateľ, ale rovnakého typu (dá sa to očakávať). Ilustruje to nasledujúci kód:

float idf = 2.5;
float * const floatPC = 0;
float * floatPter = &idf;
floatPter = floatPC; // OK
cout << floatPter << '\n';

Výstup je 0.

Dve hodnoty nulového ukazovateľa rovnakého typu sa rovnajú (==).

Ukazovateľ na typ objektu je možné priradiť k ukazovateľu void. Ilustruje to nasledujúci kód:

float idf = 2.5;
float * floatPtr = &idf;
void * vd;
vd = floatPtr;

Kód sa kompiluje bez varovania alebo chybovej správy.

Konverzie funkcie na ukazovateľ

Ukazovateľ na funkciu, ktorá by nevrhla výnimku, je možné priradiť ukazovateľu na funkciu. Ilustruje to nasledujúci kód:

#include
pomocou namespace std;
void fn1 () noexcept

cout << "with noexcept" << '\n';

void fn2 ()

//Vyhlásenia

void (* func1) () noexcept;
void (* func2) ();
int main ()

func1 = &fn1;
func2 = &fn2;
func2 = &fn1;
func2 ();
návrat 0;

Výstup je s výnimkou.

Booleovské konverzie

V jazyku C ++ zahŕňajú entity, ktorých výsledkom môže byť nepravda, hodnoty „nula“, „nulový ukazovateľ“ a „nulový ukazovateľ člena“.„Všetky ostatné entity majú za následok pravdu. Ilustruje to nasledujúci kód:

bool a = 0.0; cout << a <<'\n';
float * floatPtr = 0;
bool b = floatPtr; cout << b <<'\n';
bool c = -2.5; cout << c <<'\n';
bool d = +2.5; cout << d <<'\n';

Výstup je:

0 // pre nepravdivé
0 // pre nepravdivé
1 // za pravdu
1 // za pravdu

Lvalue, prvalue a xvalue

Zvážte nasledujúci kód:

int id = 35;
int & id1 = id;
cout << id1 << '\n';

Výstup je 35. V kóde sú id a id1 lvalue, pretože identifikujú miesto (objekt) v pamäti. Výstup 35 je prvočíslo. Akýkoľvek literál, okrem reťazcového literálu, je prvalue. Ostatné prvočísla nie sú také zrejmé, ako v nasledujúcich príkladoch. Zvážte nasledujúci kód:

int id = 62;
int * ptr = &id;
int * pter;

Ptr je hodnota, pretože identifikuje miesto (objekt) v pamäti. Na druhej strane, pter nie je hodnota. Pter je ukazovateľ, ale neidentifikuje žiadne miesto v pamäti (neukazuje na žiadny objekt). Takže pter je prvou hodnotou.

Zvážte nasledujúci kód:

void fn ()

//Vyhlásenia

void (* func) () = &fn;
float (* functn) ();

Fn () a (* func) () sú výrazy lvalue, pretože identifikujú entitu (funkciu) v pamäti. Na druhej strane, (* functn) () nie je výraz lvalue. (* functn) () je ukazovateľ na funkciu, ale neidentifikuje žiadnu entitu v pamäti (neodkazuje na žiadnu funkciu v pamäti). Takže (* functn) () je prvoradý výraz.

Zvážte nasledujúci kód:

struct S

int n;
;
S obj;

S je trieda a obj je objekt inštanovaný z triedy. Obj identifikuje objekt v pamäti. Trieda je zovšeobecnená jednotka. Takže S skutočne neidentifikuje žiadny objekt v pamäti. O S sa hovorí, že je to nemenovaný objekt. S je tiež prvoradý výraz.

Tento článok sa zameriava na prvé hodnoty. Prvalue znamená čistú rvalue.

Xvalue

Xvalue znamená Expiring Value. Dočasné hodnoty vypršajú. Z hodnoty sa môže stať hodnota x. Z prvej hodnoty sa tiež môže stať xhodnota. Tento článok sa zameriava na prvé hodnoty. Hodnota x je hodnota l alebo nepomenovaná referencia hodnoty, ktorej úložisko je možné znovu použiť (zvyčajne preto, že je takmer na konci svojej životnosti). Zvážte nasledujúci funkčný kód:

struct S

int n;
;
int q = S ().n;

Výraz „int q = S ().n; “ skopíruje akúkoľvek hodnotu n do q. S () je iba prostriedok; nejde o pravidelne používaný výraz. S () je prvá hodnota, ktorej použitie ju previedlo na hodnotu x.

Konverzie z hodnoty na r

Zvážte nasledujúce vyhlásenie:

int ii = 70;

70 je prvočíslo (rvalue) a ii je lvalue. Zvážte nasledujúci kód:

int ii = 70;
int tt = ii;

V druhom výroku sa ii nachádza v situácii prvalue, takže ii sa tam stáva prvalue. Inými slovami, kompilátor implicitne prevádza ii na prvalue. To znamená, že keď sa hodnota lvalue použije v situácii, v ktorej implementácia očakáva prvú hodnotu, implementácia prevedie hodnotu lvalue na prvú hodnotu.

Konverzie z poľa na ukazovateľ

Zvážte nasledujúci funkčný kód:

char * p;
char q [] = 'a', 'b', 'c';
p = & q [0];
++p;
cout<<*p<<'\n';

Výstup je b. Prvý príkaz je výraz a je smerníkom na znak. Na ktorý znak ale výrok smeruje? - Žiadna postava. Je to teda prvočíslo a nie hodnota. Druhým príkazom je pole, v ktorom q [] je výraz lvalue. Tretí príkaz zmení prvalue, p na výraz lvalue, ktorý ukazuje na prvý prvok poľa.

Konverzie funkcie na ukazovateľ

Zvážte nasledujúci program:

#include
pomocou namespace std;
void (* func) ();
void fn ()

//Vyhlásenia

int main ()

func = &fn;
návrat 0;

Výraz „void (* func) ();“ je ukazovateľ na funkciu. Ale na ktorú funkciu výraz smeruje? - Žiadna funkcia. Je to teda prvočíslo a nie hodnota. Fn () je definícia funkcie, kde fn je výraz lvalue. V main (): „func = &fn;”Zmení prvočíslo, func, na výraz lvalue, ktorý ukazuje na funkciu, fn ().

Dočasné konverzie materializácie

V C ++ je možné prvočíslo konvertovať na xhodnotu rovnakého typu. Ilustruje to nasledujúci kód:

struct S

int n;
;
int q = S ().n;

Tu bola prvá hodnota, S (), prevedená na xvalue. Ako hodnota x by to netrvalo dlho - ďalšie vysvetlenie nájdete vyššie.

Konverzie kvalifikácie

Typ kvalifikovaný pre životopis je typ kvalifikovaný vyhradeným slovom „const“ a / alebo vyhradeným slovom „volatile“.“

Poradie je tiež v Cv kvalifikácii. Žiadna kvalifikácia cv nie je nižšia ako kvalifikácia „const“, čo je menej ako kvalifikácia „const volatile“. Žiadna kvalifikácia cv nie je nižšia ako kvalifikácia „volatile“, čo je menej ako kvalifikácia „volatile“. Existujú teda dva okruhy poradia kvalifikácií. Jeden typ môže mať viac kvalifikácií pre životné prostredie ako iný.

Typ s nižšou prvou hodnotou kvalifikovanou pre život je možné previesť na typ s prvou hodnotou vyhovujúcou väčšej hodnote. Oba typy by mali byť ukazovateľ na cv.

Záver

Entity v C ++ je možné konvertovať z jedného typu na súvisiaci typ implicitne alebo explicitne. Programátor však musí pochopiť, na čo sa dá a čo nie je možné prevádzať. Konverzia sa môže uskutočňovať v nasledujúcich doménach: integrálne konverzie, konverzie s pohyblivou desatinnou čiarkou, pohyblivé-integrálne konverzie, zvyčajné aritmetické konverzie, konverzie ukazovateľa, konverzie z funkcie na ukazovateľ, booleovské konverzie, konverzie z hodnoty na rvalu, konverzie z poľa na ukazovateľ , Konverzie medzi funkciami a ukazovateľmi, dočasné konverzie materializácie a konverzie kvalifikácie.

Hry SuperTuxKart pre Linux
SuperTuxKart pre Linux
SuperTuxKart je vynikajúci titul navrhnutý tak, aby vám priniesol zážitok z hry Mario Kart zadarmo na vašom systéme Linux. Je to dosť náročné a zábavn...
Hry Výukový program Battle for Wesnoth
Výukový program Battle for Wesnoth
Battle for Wesnoth je jednou z najpopulárnejších open source strategických hier, ktoré si v súčasnosti môžete zahrať. Táto hra bola nielen vyvinutá ve...
Hry 0 A.D. Výukový program
0 A.D. Výukový program
Z mnohých strategických hier je tu 0 A.D. dokáže vyniknúť ako komplexný titul a veľmi hlboká, taktická hra napriek tomu, že je otvoreným zdrojom. Vývo...