C ++

Standardne pretvorbe C ++

Standardne pretvorbe C ++
V jeziku C ++ obstajata dva tipa entitet, osnovni in sestavljeni. Temeljni tipi so skalarni tipi. Sestavljeni tipi so preostali tipi entitet. Pretvorba se lahko izvede iz ene vrste entitete v drugo ustrezno vrsto. Upoštevajte naslednji program:

#include
#include
uporaba imenskega prostora std;
int main ()

int rt1 = sqrt (5);
int rt2 = sqrt (8);
cout<vrnitev 0;

Izhod je 2, 2, kar pomeni, da je program vrnil kvadratni koren 5 kot 2 in kvadratni koren 8 tudi kot 2. Torej, prvi dve trditvi v glavni () funkcije so prikrile odgovore kvadratnega korena 5 in kvadratnega korena 8. Ta članek ne obravnava tal ali stropa v jeziku C++. Ta članek obravnava pretvorbo enega tipa C ++ v drugega ustreznega tipa C ++; kar kaže na kakršen koli približek dodane ali odstranjene vrednosti, izgubo natančnosti ali omejitev. Osnovno znanje jezika C ++ je predpogoj za razumevanje tega članka.

Vsebina članka

  • Integralne konverzije
  • Pretvorbe s plavajočo vejico
  • Plavajoče-integralne pretvorbe
  • Razvrstitev celoštevilčnih pretvorb
  • Celovite promocije
  • Običajne aritmetične pretvorbe
  • Promocija s plavajočo vejico
  • Pretvorbe kazalcev
  • Funkcija pretvorbe kazalca
  • Logične pretvorbe
  • Lvalue, prvalue in xvalue
  • Xvalue
  • Pretvorbe Lvalue v rvalue
  • Pretvorbe matrike v kazalec
  • Pretvorbe funkcije v kazalec
  • Začasne konverzije materializacije
  • Pretvorbe kvalifikacij
  • Zaključek

Integralne konverzije

Integralne pretvorbe so celoštevilčne pretvorbe. Nepodpisana cela števila vključujejo "unsigned char", "unsigned short int", "unsigned int", "unsigned long int" in "unsigned long long int."Ustrezna podpisana cela števila vključujejo" podpisani znak "," kratek int "," int "," dolg int "in" dolg dolg int.”Vsak tip int mora biti v toliko bajtih kot njegov predhodnik. Za večino sistemov je mogoče eno vrsto entitete brez težav pretvoriti v ustrezno vrsto. Težava se pojavi pri pretvorbi iz večjega obsega v manjši ali pri pretvorbi podpisane številke v ustrezno nepodpisano številko.

Vsak prevajalnik ima največjo vrednost, ki jo lahko sprejme za kratek int. Če je kratkemu int dodeljeno število, ki je večje od tega maksimuma, namenjenega za int, bo prevajalnik sledil nekemu algoritmu in vrnil številko v območju kratkega int. Če ima programer srečo, bo prevajalnik opozoril na težave z uporabo neprimerne pretvorbe. Ista razlaga velja za pretvorbe drugih vrst int.

Uporabnik se mora obrniti na dokumentacijo prevajalnika, da določi mejne vrednosti za vsako vrsto entitete.

Če je treba negativno podpisano kratko int številko pretvoriti v nepodpisano kratko int številko, bo prevajalnik sledil nekemu algoritmu in vrnil pozitivno število v območju nepodpisanega kratkega int. Tovrstni pretvorbi se je treba izogibati. Ista razlaga velja za pretvorbe drugih vrst int.

Katero koli celoštevilsko število, razen 0, je mogoče pretvoriti v logično vrednost true. 0 se pretvori v logično vrednost false. Naslednja koda to ponazarja:

int a = -27647;
plovec b = 2.5;
int c = 0;
bool a1 = a;
bool b1 = b;
bool c1 = c;
cout<cout<cout<Rezultat je:

1 za res
1 za res
0 za false

Pretvorbe s plavajočo vejico

Tipi s plavajočo vejico vključujejo "float", "double" in "long double".”Vrste s plavajočo vejico niso razvrščene v podpisane in nepodpisane, na primer cela števila. Vsaka vrsta ima lahko podpisano ali nepodpisano številko. Tip s plavajočo vejico mora imeti vsaj enako natančnost kot njegov predhodnik. To pomeni, da mora imeti "dolga dvojna" enako ali večjo natančnost kot "dvojna", "dvojna" pa mora imeti enako ali večjo natančnost kot "plavajoča"."

Ne pozabite, da obseg vrste s plavajočo vejico ni neprekinjen; prej je v majhnih korakih. Večja kot je natančnost vrste, manjši so koraki in večje število bajtov za shranjevanje številke. Ko se torej število s plavajočo vejico pretvori iz vrste z nižjo natančnostjo v vrsto z večjo natančnostjo, mora programer sprejeti napačno povečanje natančnosti in morebitno povečanje števila bajtov za shranjevanje števil. Ko se število s plavajočo vejico pretvori iz vrste z večjo natančnostjo v vrsto z nižjo natančnostjo, mora programer sprejeti izgubo v natančnosti. Če je treba število bajtov za shranjevanje števil zmanjšati, bo prevajalnik sledil nekemu algoritmu in vrnil številko kot nadomestek (kar verjetno ni tisto, kar si programer želi). Upoštevajte tudi težave zunaj dosega.

Plavajoče-integralne pretvorbe

Število s plavajočo vejico se pretvori v celo število s skrajšanjem delnega dela. Naslednja koda to ponazarja:

plovec f = 56.953;
int i = f;
cout<Izhod je 56. Razponi za float in celo število morajo biti združljivi.

Ko se celo število pretvori v float, je vrednost, prikazana kot float, enaka vrednosti, ki je bila vnesena kot celo število. Vendar je lahko floatni ekvivalent natančna vrednost ali pa ima majhno delno razliko, ki ni prikazana. Razlog za delno razliko je v tem, da so številke s plavajočo vejico v računalniku predstavljene v majhnih delnih korakih, zato bi bilo natančno predstavljanje celotnega števila naključje. Čeprav je celo število, prikazano kot plovec, enako, kot je bilo vtipkano, je prikaz morda približek shranjenega.

Razvrstitev celoštevilčnih pretvorb

Vsak celoštevilski tip ima rang, ki mu je bil dodeljen. Ta razvrstitev pomaga pri pretvorbi. Razvrstitev je relativna; uvrstitve niso na določenih ravneh. Razen znaka char in sign char, nobeno podpisano celo število nima enakega ranga (ob predpostavki, da je char podpisano). Nepodpisani celoštevilski tipi imajo enako uvrstitev kot ustrezni podpisani celoštevilski tipi. Razvrstitev je naslednja:

  • Ob predpostavki, da je char podpisan, imata char in podpisani char enak rang.
  • Razred podpisanega celoštevilčnega tipa je večji od ranga podpisanega celoštevilčnega tipa manjšega števila bajtov pomnilnika. Torej, rang podpisanega dolgega dolgega int je večji od ranga podpisanega dolgega int, ki je večji od ranga podpisanega dolgega int, ki je večji od ranga podpisanega kratkega int, ki je večji od ranga podpisanega znaka.
  • Uvrstitev katerega koli podpisanega celoštevilčnega tipa je enaka rangu ustrezne podpisane celoštevilčne vrste.
  • Čin nepodpisanega znaka je enak rangu podpisanega znaka.
  • bool ima najmanj čin; njen uvrstitev je manjša od stopnje podpisanega znaka.
  • char16_t ima enak rang kot kratki int. char32_t ima enak rang kot int. Za prevajalnik g ++ ima wchar_t enak rang kot int.

Celovite promocije

Integral Promotions je Integer Promotions. Ni razloga, da celega števila manj bajtov ni mogoče predstaviti s številom večjih bajtov. Integer Promotions se ukvarja z vsem, kar sledi:

  • Podpisani kratki int (dva bajta) je mogoče pretvoriti v podpisani int (štiri bajte). Nepodpisani kratki int (dva bajta) je mogoče pretvoriti v nepodpisani int (štiri bajte). Opomba: pretvorba kratkega int v dolg int ali dolg dolg int vodi do izgube bajtov shrambe (lokacije objekta) in izgube pomnilnika. Bool, char16_t, char32_t in wchar_t so izvzeti iz te promocije (pri prevajalniku g ++ imajo char32_t in wchar_t enako število bajtov).
  • S prevajalnikom g ++ lahko tip char16_t pretvorimo v podpisan tip int ali nepodpisan tip int; tip char32_t je mogoče pretvoriti v podpisan tip int ali nepodpisan tip int; in tip wchar_t je mogoče pretvoriti v podpisan ali nepodpisan tip int.
  • Tip bool je mogoče pretvoriti v tip int. V tem primeru true postane 1 (štirje bajti) in false postane 0 (štirje bajti). Int je lahko podpisan ali podpisan.
  • Celovita promocija obstaja tudi za neobseženo vrsto oštevilčenja - glej kasneje.

Običajne aritmetične pretvorbe

Upoštevajte naslednjo kodo:

float f = 2.5;
int i = f;
cout<Koda se prevede, ne da bi navedla kakršno koli opozorilo ali napako in podala rezultat 2, kar verjetno ni tisto, kar se je pričakovalo. = je binarni operator, ker zajema levi in ​​desni operand. Upoštevajte naslednjo kodo:

int i1 = 7;
int i2 = 2;
float flt = i1 / i2;
cout<Izhod je 3, ampak to je narobe; naj bi bilo 3.5. Delitveni operator, /, je tudi binarni operater.

C ++ ima običajne aritmetične pretvorbe, ki jih mora programer poznati, da se izogne ​​napakam pri kodiranju. Običajne aritmetične pretvorbe na binarnih operatorjih so naslednje:

  • Če je kateri od operandov tipa "long double", bo drugi pretvorjen v long double.
  • V nasprotnem primeru, če je kateri od operandov dvojni, se drugi pretvori v dvojni.
  • V nasprotnem primeru, če je kateri od operandov float, se drugi pretvori v float. V zgornji kodi je rezultat i1 / i2 uradno 2; zato je flt 2. Rezultat binarnega, /, se uporabi kot desni operand za binarni operator, =. Končna vrednost 2 je torej float (ne int).

DRUGO, CELOTNA PROMOCIJA BI SE POTREBILA SPODNJE:

  • Če sta oba operanda iste vrste, potem nadaljnja pretvorba ne poteka.
  • V nasprotnem primeru, če sta oba operanda podpisana celoštevilska tipa ali pa oba nepodpisana celoštevilna tipa, bo operand tipa z nižjim celoštevilskim rangom pretvorjen v tip operanda z višjim rangom.
  • V nasprotnem primeru, če je en operand podpisan, drugi pa nepodpisan in če je vrsta nepodpisanega operanda večja ali enaka rangu vrste podpisanega operanda in če je vrednost podpisanega operanda večja ali enaka nič, potem podpisani operand bo pretvorjen v nepodpisani tip operanda (ob upoštevanju obsega). Če je podpisani operand negativen, bo prevajalnik sledil algoritmu in vrnil številko, ki morda ni sprejemljiva za programerja.
  • V nasprotnem primeru, če je en operand podpisan celoštevilski tip, drugi pa nepodpisani celoštevilčni tip in če so vse možne vrednosti vrste operanda z nepodpisanim celoštevilskim tipom predstavljene s podpisanim celoštevilskim tipom, potem bo podpisani celoštevilski tip pretvori v tip operanda podpisanega celoštevilčnega tipa.
  • V nasprotnem primeru bi bila dva operanda (na primer char in bool) pretvorjena v celoštevilsko vrsto brez podpisa.

Promocija s plavajočo vejico

Tipi s plavajočo vejico vključujejo "float", "double" in "long double".”Tip s plavajočo vejico mora imeti vsaj enako natančnost kot njegov predhodnik. Promocija s plavajočo vejico omogoča pretvorbo iz float v dvojno ali iz dvojne v dolgo dvojno.

Pretvorbe kazalcev

Kazalca ene vrste predmeta ni mogoče dodeliti kazalcu druge vrste predmeta. Naslednja koda ne bo prevedena:

int id = 6;
int * intPtr = &id;
float idf = 2.5;
float * floatPtr = &idf;
intPtr = floatPtr; // napaka tukaj

Ničelni kazalec je kazalec, katerega naslovna vrednost je nič. Ničelnega kazalca enega tipa predmeta ni mogoče dodeliti ničelnemu kazalcu drugega tipa predmeta. Naslednja koda ne bo prevedena:

int id = 6;
int * intPtr = &id;
intPtr = 0;
float idf = 2.5;
float * floatPtr = &idf;
floatPtr = 0;
intPtr = floatPtr; // napaka tukaj

Const ničelnega kazalca ene vrste predmeta ni mogoče dodeliti ničelni const kazala druge vrste predmeta. Naslednja koda ne bo prevedena:

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

Ničelni kazalec lahko za svoj tip dobi drugačno naslovno vrednost. Naslednja koda to ponazarja:

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

Izhod je 2.5.

Kot je bilo pričakovano, ničelni konstanti kazalca ni mogoče dodeliti nobene vrednosti naslova. Naslednja koda ne bo prevedena:

float idf = 2.5;
float * const floatPC = 0;
floatPC = &idf; // napaka tukaj

Vendar pa lahko običajnemu kazalcu dodelimo ničelno konstanto kazalca, vendar iste vrste (to je pričakovano). Naslednja koda to ponazarja:

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

Izhod je 0.

Dve vrednosti istega tipa ničelnih kazalcev sta primerjani (==) enaki.

Kazalec na vrsto predmeta lahko dodeli kazalcu na void. Naslednja koda to ponazarja:

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

Koda se prevede brez opozorila ali sporočila o napaki.

Funkcija pretvorbe kazalca

Kazalec na funkcijo, ki ne bo povzročila izjeme, se lahko dodeli kazalcu na funkcijo. Naslednja koda to ponazarja:

#include
uporaba imenskega prostora std;
void fn1 () noexcept

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

void fn2 ()

// izjave

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

func1 = &fn1;
func2 = &fn2;
func2 = &fn1;
func2 ();
vrnitev 0;

Izhod je z noexcept.

Logične pretvorbe

V C ++ entitete, ki lahko povzročijo false, vključujejo »nič«, »ničelni kazalec« in »ničelni kazalec člana.”Vse druge entitete povzročijo resnico. Naslednja koda to ponazarja:

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

Rezultat je:

0 // za false
0 // za false
1 // za res
1 // za res

Lvalue, prvalue in xvalue

Upoštevajte naslednjo kodo:

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

Izhod je 35. V kodi sta id in id1 vrednosti l, ker identificirata lokacijo (objekt) v pomnilniku. Izhod 35 je prva vrednost. Vsaka dobesedna črka, razen nizovne, je prva vrednost. Druge vrednosti niso tako očitne kot v naslednjih primerih. Upoštevajte naslednjo kodo:

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

Ptr je vrednost l, ker identificira lokacijo (objekt) v spominu. Po drugi strani pter ni vrednost. Pter je kazalec, vendar ne prepozna nobene lokacije v pomnilniku (ne kaže na noben predmet). Torej, pter je prva vrednost.

Upoštevajte naslednjo kodo:

void fn ()

// izjave

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

Fn () in (* func) () sta izraza vrednosti, ker identificirata entiteto (funkcijo) v pomnilniku. Po drugi strani pa (* functn) () ni izraz lvalue. (* functn) () je kazalec na funkcijo, vendar ne prepozna nobene entitete v pomnilniku (ne kaže na nobeno funkcijo v pomnilniku). Torej, (* functn) () je izraz prve vrednosti.

Zdaj upoštevajte naslednjo kodo:

struct S

int n;
;
S obj;

S je razred, obj pa objekt, ustvarjen iz razreda. Obj identificira predmet v spominu. Razred je posplošena enota. Torej, S v resnici ne prepozna nobenega predmeta v spominu. S naj bi bil neimenovani predmet. S je tudi izraz prve vrednosti.

Ta članek se osredotoča na vrednosti. Prvalue pomeni čisto rvalue.

Xvalue

Xvalue pomeni Expiring Value. Začasne vrednosti so veljavne vrednosti. Lvalue lahko postane xvalue. Prvalue lahko postane tudi xvalue. Ta članek se osredotoča na vrednosti. Xvalue je vrednost lvalue ali neimenovana referenca rvalue, katere pomnilnik je mogoče ponovno uporabiti (običajno zato, ker je blizu konca življenjske dobe). Upoštevajte naslednjo kodo, ki deluje:

struct S

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

Izraz “int q = S ().n; " kopira katero koli vrednost n v q. S () je samo sredstvo; ni redno uporabljen izraz. S () je prva vrednost, ki jo je pretvorila v vrednost xvalue.

Pretvorbe Lvalue v rvalue

Upoštevajte naslednjo izjavo:

int ii = 70;

70 je prva vrednost (rvalue) in ii je vrednost. Zdaj upoštevajte naslednjo kodo:

int ii = 70;
int tt = ii;

V drugi izjavi je ii v položaju prve vrednosti, zato ii tam postane prva vrednost. Z drugimi besedami, prevajalnik implicitno pretvori ii v prvo vrednost. To pomeni, da kadar se vrednost lvalue uporablja v situaciji, v kateri izvedba pričakuje prvo vrednost, izvedba pretvori vrednost v vrednost prva.

Pretvorbe matrike v kazalec

Upoštevajte naslednjo kodo, ki deluje:

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

Izhod je b. Prvi stavek je izraz in je kazalec na znak. Toda na kateri znak kaže izjava? - Brez znaka. Torej je prva vrednost in ne vrednost. Drugi stavek je matrika, v kateri je q [] izraz vrednosti lvalue. Tretja izjava spremeni prvo vrednost, p, v izraz lvalue, ki kaže na prvi element polja.

Pretvorbe funkcije v kazalec

Upoštevajte naslednji program:

#include
uporaba imenskega prostora std;
void (* func) ();
void fn ()

// izjave

int main ()

func = &fn;
vrnitev 0;

Izraz "void (* func) ();" je kazalec na funkcijo. Toda na katero funkcijo kaže izraz? - Brez funkcije. Torej je prva vrednost in ne vrednost. Fn () je definicija funkcije, kjer je fn izraz vrednosti. V glavnem () je "func = &fn;"Spremeni prvo vrednost, funkc, v izraz lvalue, ki kaže na funkcijo, fn ().

Začasne konverzije materializacije

V C ++ lahko prvo vrednost pretvorite v vrednost x x iste vrste. Naslednja koda to ponazarja:

struct S

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

Tu je bila prva vrednost, S (), pretvorjena v vrednost x. Kot xvalue ne bi trajalo dolgo - glej več pojasnil zgoraj.

Pretvorbe kvalifikacij

Vrsta, ki izpolnjuje pogoje za cv, je vrsta, ki jo izpolnjuje rezervirana beseda, "const" in / ali rezervirana beseda, "volatile."

Uvrščena je tudi Cv-kvalifikacija. Nobena cv-kvalifikacija ni manjša od kvalifikacije „const“, kar je manj kot kvalifikacija „const volatile“. Nobena cv-kvalifikacija ni manjša od kvalifikacije „volatile“, kar je manj kot kvalifikacija „const volatile“. Torej obstajata dva toka kvalifikacijske razvrstitve. Ena vrsta je lahko bolj kvalificirana za cv kot druga.

Nižjo ceno, ki izpolnjuje pogoje cv, je mogoče pretvoriti v cv z najvišjo cv. Obe vrsti bi morali biti kazalec na cv.

Zaključek

Entitete C ++ je mogoče implicitno ali eksplicitno pretvoriti iz enega tipa v soroden tip. Programer pa mora razumeti, kaj je mogoče pretvoriti in kaj ne, in v kakšno obliko. Pretvorba se lahko izvede na naslednjih področjih: Integralne pretvorbe, Pretvorbe s plavajočo vejico, Pretvorbe s plavajočo vejico, Običajne aritmetične pretvorbe, Pretvorbe kazalcev, Pretvorba funkcije v kazalec, Logične pretvorbe, Pretvorbe Lvalue-to-Rvalue, Pretvorbe polja v kazalec , Pretvorbe funkcije do kazalca, začasne pretvorbe materializacije in pretvorbe kvalifikacij.

Najboljši Linux Distros za igre na srečo v letu 2021
Operacijski sistem Linux je daleč od prvotnega, preprostega, strežniškega videza. Ta OS se je v zadnjih letih izjemno izboljšal in se je zdaj razvil v...
Kako zajeti in pretakati svojo igralno sejo v Linuxu
V preteklosti je bilo igranje iger le hobi, sčasoma pa je igralniška industrija zabeležila veliko rast glede tehnologije in števila igralcev. Občinstv...
Najboljše igre z ročnim sledenjem
Oculus Quest je pred kratkim predstavil odlično idejo ročnega sledenja brez krmilnikov. Z vedno večjim številom iger in dejavnosti, ki izvajajo podpor...