C ++

C ++ standard konverziók

C ++ standard konverziók
A C ++ - ban két entitástípus létezik, az alaptípusok és az összetett típusok. Az alapvető típusok a skaláris típusok. Az összetett típusok a többi entitástípus. Konvertálás történhet egyik entitástípusból egy másik megfelelő típusba. Fontolja meg a következő programot:

#include
#include
névtér használata std;
int main ()

int rt1 = sqrt (5);
int rt2 = sqrt (8);
cout<visszatér 0;

A kimenet az 2, 2, ami azt jelenti, hogy a program az 5 négyzetgyökét 2-nek, a 8 négyzetgyökét pedig szintén 2-nek adta vissza. Tehát, az első két állítás a fő() függvény az 5 négyzetgyök és a 8 négyzetgyök válaszait tárolja. Ez a cikk nem tárgyalja a padlóburkolatot vagy a mennyezetet a C-ben++. Inkább ez a cikk az egyik C ++ típus átalakítását egy másik megfelelő C ++ típussá tárgyalja; a hozzáadott vagy eltávolított esetleges hozzávetőleges érték, a pontosság elvesztése vagy a korlátozás feltüntetése. A cikk megértésének előfeltétele a C ++ alapvető ismerete.

A cikk tartalma

  • Integrált konverziók
  • Lebegőpontos konverziók
  • Lebegő-integrált konverziók
  • Egész konverziós rangsor
  • Integrált promóciók
  • Szokásos számtani konverziók
  • Lebegőpontos promóció
  • Mutató konverziók
  • Funkció mutatókonverziókhoz
  • Logikai konverziók
  • Lvalue, prvalue és xvalue
  • Xvalue
  • Lvalue-to-value konverziók
  • Tömb-mutató konverziók
  • Funkció-mutató konverziók
  • Ideiglenes materializálási konverziók
  • Minősítési konverziók
  • Következtetés

Integrált konverziók

Az integrált konverziók egész számok. Az aláíratlan egész számok tartalmazzák az „előjel nélküli karaktert”, az „előjel nélküli rövid int”, az „aláíratlan int”, a „nem jelölt hosszú int” és a „nem jelölt hosszú hosszú int” elemeket.”A megfelelő előjeles egész számok közé tartozik az„ aláírt karakter ”,„ rövid int ”,„ int ”,„ hosszú int ”és„ hosszú hosszú int ”.”Minden int típust annyi bájtban kell tárolni, mint elődje. A legtöbb rendszerben egy entitástípus probléma nélkül konvertálható egy megfelelő típusra. A probléma akkor fordul elő, ha nagyobb tartománytípust alakít át kisebb tartománytípussá, vagy amikor aláírt számot alakít át megfelelő aláíratlan számra.

Minden fordítónak van egy maximális értéke, amelyet a rövid int-re vehet. Ha ennél a maximumnál nagyobb számot rendelünk egy int-hez, akkor a rövid int-hez a fordító valamilyen algoritmust követ, és egy számot ad vissza a rövid int tartományán belül. Ha a programozónak szerencséje van, a fordító figyelmeztet a nem megfelelő konverzió használatával kapcsolatos problémákra. Ugyanez a magyarázat vonatkozik más int típusú konverziókra is.

A felhasználónak tanulmányoznia kell a fordító dokumentációját, hogy meghatározza az egyes entitástípusok határértékeit.

Ha egy negatív előjelű rövid int számot konvertálni kell előjel nélküli rövid int számra, akkor a fordító követi valamilyen algoritmust, és pozitív számot ad vissza az aláíratlan rövid int tartományán belül. Ezt a fajta átalakulást el kell kerülni. Ugyanez a magyarázat vonatkozik más int típusú konverziókra is.

A 0 kivételével bármely egész szám konvertálható logikai igazra. A 0-t logikai hamisra konvertálja. A következő kód ezt szemlélteti:

int a = -27647;
úszó b = 2.5;
int c = 0;
bool a1 = a;
bool b1 = b;
bool c1 = c;
cout<cout<cout<A kimenet:

1 igaz
1 igaz
0 hamis

Lebegőpontos konverziók

A lebegőpontos típusok közé tartozik az „úszó”, a „kettős” és a „hosszú kettős”.”A lebegőpontos típusok nincsenek aláírva és aláíratlanul csoportosítva, például egész számok. Minden típusnak lehet aláírt vagy aláíratlan száma. Egy lebegőpontos típusnak legalább ugyanolyan pontosságúnak kell lennie, mint elődjének. Vagyis a „hosszú kettős” pontosságának egyenlőnek vagy nagyobbnak kell lennie a „kettősnek”, a „kettősnek” pedig legalább egy pontosságúnak kell lennie a „lebegéshez”.”

Ne feledje, hogy a lebegőpontos tartomány nem folyamatos; inkább kis lépésekben. Minél nagyobb a pontosság a típusnál, annál kisebbek a lépések és annál nagyobb a bájtok száma a szám tárolásához. Tehát, ha egy lebegőpontos számot alacsonyabb pontosságú típusból nagyobb pontosságúvá alakítunk át, a programozónak el kell fogadnia a pontosság hamis növekedését és a bájtok számának esetleges növekedését a számok tárolásához. Amikor egy lebegőpontos számot nagyobb pontosságú típusból alacsonyabb pontosságúvá alakítunk át, a programozónak el kell fogadnia a pontosság veszteségét. Ha csökkenteni kell a bájtok számát a számok tárolásához, akkor a fordító követi valamilyen algoritmust, és egy számot ad vissza helyettesítőnek (valószínűleg nem ezt akarja a programozó). Ne feledje a tartományon kívüli problémákat is.

Lebegő-integrált konverziók

A lebegőpontos számot a törtrész levágásával egész számra konvertáljuk. A következő kód ezt szemlélteti:

úszó f = 56.953;
int i = f;
cout<A kimenet az 56. Az úszó és az egész tartománynak kompatibilisnek kell lennie.

Amikor egy egész számot úszóvá alakítunk, az úszóként megjelenített érték megegyezik azzal, amelyet egész számként írtunk be. Az úszóegyenérték azonban lehet a pontos érték, vagy enyhe töredékkülönbséggel rendelkezik, amely nem jelenik meg. A töredékkülönbség oka az, hogy a lebegőpontos számok kis töredékekben vannak ábrázolva a számítógépben, így az egész szám pontos ábrázolása egybeesés lenne. Tehát, bár az úszóként megjelenített egész szám megegyezik a beírt értékkel, a kijelző a becsült értéket jelentheti.

Egész konverziós rangsor

Bármely egész típusúnak van rangja, amelyet kapott. Ez a rangsor segíti a konverziót. A rangsor relatív; a rangok nincsenek rögzített szinten. A char és az aláírt char kivételével két aláírt egész számnak nincs azonos rangja (feltételezve, hogy a char alá van írva). Az előjel nélküli egész típusok rangsorolása megegyezik a megfelelő aláírt egész típusú típusokkal. A rangsor a következő:

  • Feltéve, hogy a char alá van írva, akkor a char és az aláírt char azonos ranggal rendelkezik.
  • Az előjeles egész típus rangja nagyobb, mint egy kisebb számú tároló bájt aláírt egész típusú típus rangja. Tehát az aláírt hosszú hosszú int rangja nagyobb, mint az aláírt hosszú int rangja, ami nagyobb, mint az aláírt int rangja, amely nagyobb, mint az aláírt rövid int rangja, ami nagyobb, mint az aláírt char rangja.
  • Bármely előjel nélküli egész típus rangja megegyezik a megfelelő aláírt egész típus rangjával.
  • Az aláíratlan char rangja megegyezik az aláírt char rangjával.
  • a bool a legkevesebb rangú; rangja alacsonyabb, mint az aláírt charé.
  • A char16_t ugyanolyan rangú, mint a rövid int. A char32_t rangja megegyezik az int. A g ++ fordító számára a wchar_t ugyanazzal a ranggal rendelkezik, mint az int.

Integrált promóciók

Az integrált promóciók az egész promóciók. Nincs oka annak, hogy a kevesebb bájtból álló egész számot nem lehet nagyobb bájtú egész számmal ábrázolni. Az Egész promóciók az alábbiakkal foglalkoznak:

  • Aláírt rövid int (két bájt) konvertálható aláírt int (négy bájt). Aláíratlan rövid int (két bájt) átalakítható aláíratlan int-vé (négy bájt). Megjegyzés: A rövid int hosszúra vagy a hosszú hosszúra történő átalakítása tárhely (objektum hely) bájtok pazarlásához és memóriapazarláshoz vezet. A Bool, a char16_t, a char32_t és a wchar_t mentesül a promóció alól (a g ++ fordítóval a char32_t és a wchar_t azonos számú bájttal rendelkezik).
  • A g ++ fordítóval a char16_t típus átalakítható aláírt int vagy aláíratlan int típusokká; a char32_t típus átalakítható aláírt int típusgá vagy aláíratlan int típusgá; és a wchar_t típus átalakítható aláírt vagy aláíratlan int típusokká.
  • A bool típus konvertálható int típusúvá. Ebben az esetben az igaz 1 (négy bájt), a hamis 0 (négy bájt) lesz. Az Int aláírható vagy aláírható.
  • Egységes promóció létezik a fel nem sorolt ​​felsorolási típus esetében is - lásd később.

Szokásos számtani konverziók

Vegye figyelembe a következő kódot:

úszó f = 2.5;
int i = f;
cout<A kód fordít anélkül, hogy bármilyen figyelmeztetést vagy hibát jelezne, megadva a kimenetet 2, amire valószínűleg nem számítottak. = bináris operátor, mert bal és jobb operandusra van szükség. Vegye figyelembe a következő kódot:

int i1 = 7;
int i2 = 2;
úszó flt = i1 / i2;
cout<A kimenet az 3, de ez helytelen; állítólag 3.5. Az osztási operátor, /, szintén bináris operátor.

A C ++ szokásos számtani átalakításokkal rendelkezik, amelyeket a programozónak tudnia kell, hogy elkerülje a kódolási hibákat. A bináris operátorok szokásos számtani konverziói a következők:

  • Ha bármelyik operandus „hosszú kettős” típusú, akkor a másik hosszú kettőssé alakul.
  • Egyébként, ha bármelyik operandus kettős, akkor a másik kettőssé alakul.
  • Egyébként, ha bármelyik operandus lebeg, akkor a másik úszóvá alakul. A fenti kódban az i1 / i2 eredménye hivatalosan 2; ezért a flt 2. A (/) bináris eredményt megfelelő operandusként alkalmazzuk a = bináris operátorra. Tehát a 2 végső értéke egy úszó (nem egy int).

EGYÉB, INTEGER TÁMOGATÁS KÖVETKEZŐ:

  • Ha mindkét operandus azonos típusú, akkor további átalakítás nem történik.
  • Egyébként, ha mindkét operandus előjeles egész típusú, vagy mindkettő előjel nélküli egész típusú, akkor az alacsonyabb egész rangú típusú operandus átalakul a magasabb rangú operandus típusává.
  • Egyébként, ha az egyik operandus alá van írva, a másik pedig nincs aláírva, és ha az aláíratlan operandus típusa nagyobb vagy egyenlő az aláírt operandus típus rangjával, és ha az aláírt operandus értéke nagyobb vagy egyenlő nulla, akkor az aláírt operandus átalakul előjel nélküli operandus típusra (figyelembe véve a tartományt). Ha az aláírt operandus negatív, akkor a fordító egy algoritmust követ, és egy olyan számot ad vissza, amely nem biztos, hogy elfogadható a programozó számára.
  • Egyébként, ha az egyik operandus előjeles egész típusú, a másik pedig előjel nélküli egész típusú, és ha az aláíratlan egész típusú típussal rendelkező operandus típusának összes lehetséges értéke aláírt egész típusú, akkor az előjel nélküli egész típus konvertálni kell az aláírt egész típusú operandus típusára.
  • Egyébként a két operandus (például egy char és egy bool) átalakításra kerülne aláíratlan egész típusúvá.

Lebegőpontos promóció

A lebegőpontos típusok közé tartozik az „úszó”, a „kettős” és a „hosszú kettős”.”A lebegőpontos típusnak legalább ugyanolyan pontossággal kell rendelkeznie, mint elődjének. A lebegőpontos promóció lehetővé teszi az úszóról kettősre vagy a kettősről a hosszú kettősre való átalakítást.

Mutató konverziók

Egy objektumtípusú mutató nem rendelhető más objektumtípusú mutatóhoz. A következő kód nem áll össze:

int id = 6;
int * intPtr = &id;
float idf = 2.5;
float * floatPtr = &idf;
intPtr = floatPtr; // hiba itt

A null mutató olyan mutató, amelynek címértéke nulla. Egy objektumtípusú null mutató nem rendelhető más objektumtípusú null mutatóhoz. A következő kód nem áll össze:

int id = 6;
int * intPtr = &id;
intPtr = 0;
float idf = 2.5;
float * floatPtr = &idf;
floatPtr = 0;
intPtr = floatPtr; // hiba itt

Egy objektumtípus null mutatójának konstansa nem rendelhető egy másik objektumtípus null mutatójának konstansához. A következő kód nem áll össze:

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

A null mutatóhoz különböző címérték adható a típusához. A következő kód ezt szemlélteti:

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

A kimenet az 2.5.

A várakozásoknak megfelelően egy null mutató állandóhoz nem rendelhető semmilyen típusú címérték. A következő kód nem áll össze:

float idf = 2.5;
float * const floatPC = 0;
floatPC = &idf; // hiba itt

Azonban egy közönséges mutatóhoz null pointer konstans rendelhető, de ugyanolyan típusú (ez várható). A következő kód ezt szemlélteti:

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

A kimenet az 0.

Két ugyanolyan típusú null mutatóérték egyenlő (==).

Egy objektumtípus mutatója hozzárendelhető az érvénytelenítéshez mutatóhoz. A következő kód ezt szemlélteti:

float idf = 2.5;
float * floatPtr = &idf;
érvénytelen * vd;
vd = floatPtr;

A kód figyelmeztetés vagy hibaüzenet nélkül áll össze.

Funkció mutatókonverziókhoz

Olyan függvény mutatója, amely nem dobna kivételt, hozzárendelhető egy működőképes mutatóhoz. A következő kód ezt szemlélteti:

#include
névtér használata std;
void fn1 () noexcept

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

void fn2 ()

// állítások

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

func1 = &fn1;
func2 = &fn2;
func2 = &fn1;
func2 ();
visszatér 0;

A kimenet az kivéve.

Logikai konverziók

A C ++ nyelven az entitások, amelyek hamis eredményt eredményezhetnek, tartalmazzák a „nulla”, „null mutató” és „null tag mutató” elemeket.”Minden más entitás igazat eredményez. A következő kód ezt szemlélteti:

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';

A kimenet:

0 // hamis
0 // hamis
1 // igaz
1 // igaz

Lvalue, prvalue és xvalue

Vegye figyelembe a következő kódot:

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

A kimenet az 35. A kódban az id és az id1 értékek, mert azonosítanak egy helyet (objektumot) a memóriában. A 35 kimenet előérték. Bármely literál, kivéve a string literal, prvalue. Más prvalues ​​nem annyira nyilvánvaló, mint a következő példákban. Vegye figyelembe a következő kódot:

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

A Ptr egy érték, mert azonosít egy helyet (objektumot) a memóriában. Másrészt a pter nem érték. A Pter mutató, de nem azonosít semmilyen helyet a memóriában (nem mutat objektumot). Tehát a pter egy prvalue.

Vegye figyelembe a következő kódot:

void fn ()

// állítások

void (* func) () = &fn;
úszó (* functn) ();

Az Fn () és (* func) () értékértékek, mivel azonosítanak egy elemet (függvényt) a memóriában. Másrészt a (* functn) () nem értékérték. (* functn) () egy függvény mutatója, de nem azonosít semmilyen entitást a memóriában (nem mutat a memóriában lévő egyetlen funkcióra sem). Tehát a (* functn) () egy prvalue kifejezés.

Most vegye figyelembe a következő kódot:

struct S

int n;
;
S obj;

S egy osztály, az obj pedig az osztályból példányosított objektum. Az Obj azonosítja a memóriában lévő objektumot. Az osztály általánosított egység. Tehát S nem igazán azonosít egyetlen objektumot sem a memóriában. Azt mondják, hogy S meg nem nevezett objektum. Az S szintén prvalue kifejezés.

A cikk középpontjában az értékek állnak. Az érték jelentése tiszta érték.

Xvalue

Az Xvalue a lejáró értéket jelenti. Az ideiglenes értékek lejáró értékek. Egy lvalue-ból xvalue válhat. Egy prvalue xvalue-vá is válhat. A cikk középpontjában az értékek állnak. Az xvalue egy lvalue vagy egy meg nem nevezett rvalue hivatkozás, amelynek tárhelye újrafelhasználható (általában azért, mert az élettartama végéhez közeledik). Vegye figyelembe a következő működő kódot:

struct S

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

Az „int q = S ()” kifejezés.n; ” az n értéket q értékre másolja. S () csak egy eszköz; ez nem rendszeresen használt kifejezés. Az S () olyan prvalue, amelynek használata átalakította xvalue értékké.

Lvalue-to-value konverziók

Vegye figyelembe a következő állítást:

int ii = 70;

70 egy prvalue (rvalue), az ii pedig egy lvalue. Most vegye figyelembe a következő kódot:

int ii = 70;
int tt = ii;

A második állításban az ii egy prvalue helyzetben van, tehát ii a prvalue értékké válik. Más szavakkal, a fordító a ii-t implicit módon prvalue-vá konvertálja. Vagyis amikor egy lvalue értéket használnak olyan helyzetben, amelyben a megvalósítás prvalue-ra számít, a megvalósítás átalakítja az lvalue értéket prvalue értékre.

Tömb-mutató konverziók

Vegye figyelembe a következő működő kódot:

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

A kimenet az b. Az első állítás kifejezés, és mutató egy karakterre. De melyik karakterre mutat az állítás? - Nincs karakter. Tehát ez egy prvalue és nem lvalue. A második utasítás egy tömb, amelyben a q [] értékérték. A harmadik utasítás a prvalue értéket p alakítja lvalue kifejezéssé, amely a tömb első elemére mutat.

Funkció-mutató konverziók

Fontolja meg a következő programot:

#include
névtér használata std;
void (* func) ();
void fn ()

// állítások

int main ()

func = &fn;
visszatér 0;

A „void (* func) ();” kifejezés egy függvény mutatója. De melyik függvényre mutat a kifejezés? - Nincs funkció. Tehát ez egy prvalue és nem lvalue. Az Fn () egy függvénydefiníció, ahol az fn egy érték kifejezés. A fő (), „func = &fn;”A prvalue, func értéket egy lvalue kifejezéssé alakítja, amely az fn () függvényre mutat.

Ideiglenes materializálási konverziók

A C ++ nyelven egy prvalue átalakítható ugyanolyan típusú xvalue értékre. A következő kód ezt szemlélteti:

struct S

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

Itt az S () prvalue értéket átalakítottuk xvalue értékre. Xvalue-ként nem tartana sokáig - lásd a fenti magyarázatot.

Minősítési konverziók

A CV minősítésű típus a fenntartott szó, az „const” és / vagy a „volatile”.”

A CV minősítést is rangsorolják. Egyetlen CV minősítés sem kevesebb, mint a „const” képesítés, ami kevesebb, mint a „const volatile” képesítés. Egyetlen CV minősítés sem kevesebb, mint a „volatilis” képesítés, ami kevesebb, mint a „konstans illékony” képesítés. Tehát a kvalifikációs rangsornak két iránya van. Egy típus lehet több CV minősítésű, mint egy másik.

Alacsonyabb prvalue CV minősítésű típus konvertálható cv minősítettebb prvalue típusra. Mindkét típusnak mutató-CV-nek kell lennie.

Következtetés

A C ++ entitások implicit vagy explicit módon konvertálhatók egy típusból egy kapcsolódó típusba. A programozónak azonban meg kell értenie, mit lehet átalakítani és mit nem, és milyen formába. Az átalakítás a következő területeken történhet: Integrált konverziók, Lebegőpontos konverziók, Lebegő-integrált konverziók, Szokásos aritmetikai konverziók, Mutatókonverziók, Funkció-mutató konverziók, Logikai konverziók, Érték-érték értékek, Tömb-mutató konverziók , Funkció-mutató konverziók, Ideiglenes materializálási konverziók és Minősítési konverziók.

Csata a Wesnoth bemutatóért
A Battle for Wesnoth az egyik legnépszerűbb nyílt forráskódú stratégiai játék, amelyet jelenleg játszhatsz. Ez a játék nem csak nagyon hosszú ideje fe...
0 A.D. Bemutató
A sok stratégiai játék közül 0 A.D. átfogó címként és nagyon mély, taktikus játékként képes kiemelkednie annak ellenére, hogy nyílt forráskódú. A játé...
Unity3D bemutató
Bevezetés a Unity 3D-be Az Unity 3D egy erőteljes játékfejlesztő motor. Ez több platformon keresztül lehetővé teszi játékok, mobil, webes, asztali és ...