C ++ standardkonverteringer

C ++ standardkonverteringer
Det er to enhetstyper i C ++, de grunnleggende typene og sammensatte typer. De grunnleggende typene er skalartypene. Forbindelsestypene er resten av enhetstypene. Konvertering kan finne sted fra en enhetstype til en annen passende type. Tenk på følgende program: #include
#inkludere
ved hjelp av navneområdet STD;
int main ()

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

Utgangen er 2, 2, noe som betyr at programmet har returnert kvadratroten til 5 som 2 og kvadratroten av 8 også som 2. Så de to første uttalelsene i hoved() funksjonen har fløtt svarene på kvadratroten på 5 og kvadratroten av 8. Denne artikkelen diskuterer ikke gulv eller tak i C++. Snarere diskuterer denne artikkelen konvertering av en C ++ -type til en annen passende C ++ -type; som indikerer enhver tilnærming i utført verdi, tap av presisjon eller begrensning tilsatt eller fjernet. Grunnleggende kunnskap om C ++ er en forutsetning for å forstå denne artikkelen.

Artikkelinnhold

  • Integrerte konverteringer
  • Flytende punktkonverteringer
  • Flytende integrale konverteringer
  • Heltallkonverteringsrangering
  • Integrerte kampanjer
  • Vanlige aritmetiske konverteringer
  • Flytende punktfremmende promotering
  • Pekerkonverteringer
  • Funksjon til pekerkonverteringer
  • Boolske konverteringer
  • Lvalue, prvalue og xvalue
  • Xvalue
  • Lvalue-to-Rvalue-konverteringer
  • Array-to-Pointer-konverteringer
  • Funksjon-til-peker konverteringer
  • Midlertidige materialiseringskonverteringer
  • Kvalifikasjonskonverteringer
  • Konklusjon

Integrerte konverteringer

Integrerte konverteringer er heltallkonverteringer. Usignede heltall inkluderer "usignert røye", "usignert kort int," "usignert int," "usignert lang int," og "usignert lang lang int.”De tilsvarende signerte heltallene inkluderer“ Signed Char ”,“ Short Int ”,“ Int ”,“ Long Int, ”og“ Long Long Int.”Hver INT -type skal holdes i så mange byte som forgjengeren. For de fleste systemer kan en enhetstype konverteres til en tilsvarende type uten problemer. Problemet oppstår når du konverterer fra en større rekkevidde til en mindre rekkevidde, eller når du konverterer et signert nummer til et tilsvarende usignert nummer.

Hver kompilator har en maksimal verdi som den kan ta for den korte int. Hvis et tall høyere enn det maksimum, ment for en int, er tildelt den korte int, vil kompilatoren følge noen algoritme og returnere et tall innenfor området for kort int. Hvis programmereren er heldig, vil kompilatoren advare om problemer med å bruke upassende konvertering. Den samme forklaringen gjelder konvertering av andre INT -typer.

Brukeren skal konsultere dokumentasjonen til kompilatoren for å bestemme begrensningsverdiene for hver enhetstype.

Hvis et negativt signert kort INT -nummer skal konverteres til et usignert kort INT -nummer, vil kompilatoren følge noen algoritme og returnere et positivt tall innenfor området usignet kort int. Denne typen konvertering bør unngås. Den samme forklaringen gjelder konvertering av andre INT -typer.

Ethvert heltallnummer, unntatt 0, kan konverteres til boolsk sann. 0 blir konvertert til boolsk falsk. Følgende kode illustrerer dette:

int a = -27647;
FLOAT B = 2.5;
int c = 0;
bool a1 = a;
bool b1 = b;
bool c1 = c;
cout<cout<cout<Utgangen er:

1
1
0

1 betyr sann, og 0 betyr usant i utgangen

Flytende punktkonverteringer

Flytepunkttyper inkluderer "Float", "Double" og "Long Double.”Flytende punkttyper er ikke gruppert i signerte og usignerte, som heltall. Hver type kan ha et signert eller usignert nummer. En flytende punkttype skal ha minst samme presisjon som forgjengeren. Det vil si at "lang dobbel" skal ha lik eller større presisjon til "dobbelt" og "dobbelt" skal ha lik eller større presisjon til "flyte.”

Husk at området for en flytende punkttype ikke er kontinuerlig; Snarere er det i små trinn. Jo større presisjon av typen, desto mindre trinn, og desto større er antall byte som skal lagre nummeret. Så når et flytende punktnummer konverteres fra en lavere presisjonstype til en høyere presisjonstype, må programmereren godta en falsk økning i presisjon og en mulig økning i antall byte for antall lagring. Når et flytende punktnummer konverteres fra en høyere presisjonstype til en lavere presisjonstype, må programmereren godta tap i presisjon. Hvis antallet byte for antall lagringsplasser må reduseres, vil kompilatoren følge noen algoritme og returnere et tall som erstatning (som sannsynligvis ikke er det programmereren vil ha). Husk også problemer med utenfor rekkevidde.

Flytende integrale konverteringer

Et flytende punktnummer blir konvertert til et heltall ved å avkutte av den brøkdelte delen. Følgende kode illustrerer dette:

FLOAT F = 56.953;
int i = f;
cout<Utgangen er 56. Områdene for flottøren og heltallet må være kompatible.

Når et heltall konverteres til en flottør, er verdien som vises som en flottør den samme som ble skrevet inn som et heltall. Imidlertid kan flytekvivalenten være den nøyaktige verdien eller ha en liten brøkforskjell som ikke vises. Årsaken til brøkforskjellen er at flytende punkttall er representert i datamaskinen i små brøktrinn, og at det å representere heltallet nøyaktig ville være en tilfeldighet. Så selv om heltalet som vises som en flottør er det samme som ble skrevet, kan skjermen være en tilnærming av det som er lagret.

Heltallkonverteringsrangering

Enhver heltallstype har en rangering som er gitt til den. Denne rangeringen hjelper til med konvertering. Rangeringen er relativ; Rekkene er ikke på faste nivåer. Bortsett fra Char og signert Char, har ingen to signerte heltall samme rangering (forutsatt at Char er signert). Usignede heltalltyper har samme rangering som deres tilsvarende signerte heltalltyper. Rangeringen er som følger:

  • Forutsatt at Char er signert, så har Char og signert Char samme rangering.
  • Rangeringen av en signert heltallstype er større enn rangering av en signert heltallstype av et mindre antall lagringsbyte. Så rangering av signert lang lang Int er større enn rangering av signert lang Int, som er større enn rangering av signert int, noe som er større enn rangering av signert kort int, noe som er større enn rangering av signert røye.
  • Rangeringen av en hvilken som helst usignert heltallstype tilsvarer rangering av den tilsvarende signerte heltallstypen.
  • Rangeringen av usignert røye tilsvarer rangering av signert røye.
  • Bool har minst rang; Rangeringen er mindre enn den for signert røye.
  • char16_t har samme rangering som den korte int. char32_t har samme rangering som int. For G ++ -kompilatoren har WCHAR_T samme rangering som Int.

Integrerte kampanjer

Integrerte kampanjer er heltallkampanjer. Det er ingen grunn til at et heltall med færre byte ikke kan representeres av et heltall med større byte. Heltallkampanjer tar for seg alt som følger:

  • En signert kort int (to byte) kan konverteres til en signert int (fire byte). En usignert kort int (to byte) kan konverteres til en usignert int (fire byte). Merk: Konvertering av en kort int til en lang int eller lang lang lang Int fører til sløsing med lagring (objektsted) byte og bortkastet minne. Bool, char16_t, char32_t og wchar_t er fritatt for denne kampanjen (med G ++ -kompilatoren, char32_t og wchar_t har samme antall byte).
  • Med G ++ -kompilatoren kan en Char16_T -type konverteres til en signert INT -type eller en usignert INT -type; En char32_t -type kan konverteres til en signert INT -type eller en usignert INT -type; og en WCHAR_T -type kan konverteres til en signert eller usignert INT -type.
  • En bool -type kan konverteres til en INT -type. I dette tilfellet blir True 1 (fire byte) og falsk blir 0 (fire byte). Int kan signeres eller signeres.
  • Heltallkampanje eksisterer også for usikret oppregningstype - se senere.

Vanlige aritmetiske konverteringer

Tenk på følgende kode:

FLOAT F = 2.5;
int i = f;
cout<Koden samles uten å indikere noen advarsel eller feil, og gir utdataene fra 2, som sannsynligvis ikke er det som var forventet. = er en binær operatør fordi den tar en venstre og høyre operand. Tenk på følgende kode:

int i1 = 7;
int i2 = 2;
FLOAT FLT = I1 / I2;
cout<Utgangen er 3, Men dette er galt; det skulle være 3.5. Divisjonsoperatøren, /, er også en binær operatør.

C ++ har vanlige aritmetiske konverteringer som programmereren må vite for å unngå feil i koding. De vanlige aritmetiske konverteringene på binære operatører er som følger:

  • Hvis en av operandene er av typen "lang dobbel", vil den andre bli konvertert til lang dobbel.
  • Ellers, hvis en av operandene er dobbelt, vil den andre bli konvertert til dobbelt.
  • Ellers, hvis en av operandene er flyte, vil den andre bli omgjort til flyte. I koden ovenfor er resultatet av I1/I2 offisielt 2; det er grunnen til at FLT er 2. Resultatet av den binære, /, brukes som riktig operand til den binære operatøren, = =. Så den endelige verdien av 2 er en flottør (ikke en int).

Ellers vil heltallkampanje finne sted som følger:

  • Hvis begge operandene er av samme type, finner ingen ytterligere konvertering sted.
  • Ellers, hvis begge operandene er signert heltalltyper eller begge er usignerte heltalltyper, vil operanden av typen med den nedre heltall rangering bli konvertert til typen operand med høyere rangering.
  • Ellers, hvis den ene operanden er signert og den andre er usignert, og hvis den usignerte operandtypen er større enn eller lik rangering av den signerte operandtypen, og hvis verdien av den signerte operanden er større enn eller lik null, så så Den signerte operanden vil bli konvertert til den usignerte operandtypen (med rekkevidde tatt i betraktning). Hvis den signerte operanden er negativ, vil kompilatoren følge en algoritme og returnere et tall som kanskje ikke er akseptabel for programmereren.
  • Ellers, hvis den ene operanden er en signert heltallstype og den andre er en usignert heltallstype, og hvis alle mulige verdier av typen operand med den usignerte heltallstypen kan representeres med den signerte heltalltypen, vil den usignerte heltalltypen bli konvertert til typen operand av den signerte heltalltypen.
  • Ellers ville de to operandene (en røye og en bool, for eksempel) bli konvertert til den usignerte heltallstypen.

Flytende punktfremmende promotering

Flytepunkttyper inkluderer "Float", "Double" og "Long Double.”En flytende punkttype skal ha minst samme presisjon som forgjengeren. Floating-Point-promotering gir mulighet for konvertering fra float til dobbel eller fra dobbelt til lang dobbel.

Pekerkonverteringer

En peker av en objekttype kan ikke tildeles en peker av en annen objekttype. Følgende kode vil ikke sammenstille:

int id = 6;
int* intPtr = &id;
FLOAT IDF = 2.5;
float* floatPtr = &idf;
IntPtr = FloatPtr; // Feil her

En nullpeker er en peker hvis adresseverdi er null. En nullpeker av en objekttype kan ikke tilordnes en nullpeker av en annen objekttype. Følgende kode vil ikke sammenstille:

int id = 6;
int* intPtr = &id;
intPTR = 0;
FLOAT IDF = 2.5;
float* floatPtr = &idf;
floatPtr = 0;
IntPtr = FloatPtr; // Feil her

En nullpeker const av en objekttype kan ikke tilordnes en nullpeker const av en annen objekttype. Følgende kode vil ikke sammenstille:

int id = 6;
int* intPtr = &id;
int* const intpc = 0;
FLOAT IDF = 2.5;
float* floatPtr = &idf;
float* const floatpc = 0;
INTPC = floatpc; // Feil her

En nullpeker kan gis en annen adresseverdi for sin type. Følgende kode illustrerer dette:

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

Utgangen er 2.5.

Som forventet kan en nullpekerkonstant ikke tildeles noen adresseverdi av sin type. Følgende kode vil ikke sammenstille:

FLOAT IDF = 2.5;
float* const floatpc = 0;
floatpc = &idf; // Feil her

Imidlertid kan en nullpekerkonstant tilordnes en vanlig peker, men av samme type (dette er å forvente). Følgende kode illustrerer dette:

FLOAT IDF = 2.5;
float* const floatpc = 0;
float* floatpter = &idf;
floatpter = floatpc; // OK
cout << floatPter << '\n';

Utgangen er 0.

To nullpekerverdier av samme type sammenligne (==) like.

En peker til en objekttype kan tilordnes en peker for å bli ugyldig. Følgende kode illustrerer dette:

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

Koden kompilerer uten advarsel eller feilmelding.

Funksjon til pekerkonverteringer

En peker til en funksjon som ikke vil kaste et unntak, kan tilordnes en peker for å fungere. Følgende kode illustrerer dette:

#inkludere
ved hjelp av navneområdet STD;
ugyldig FN1 () NOEXCEPT

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

ugyldig fn2 ()

// uttalelser

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

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

Utgangen er med ingen unntak.

Boolske konverteringer

I C ++ inkluderer enheter som kan resultere i falske "null", "Null Pointer" og "Null Member Pointer.”Alle andre enheter resulterer i sann. Følgende kode illustrerer dette:

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

Utgangen er:

0 // for falsk
0 // for falsk
1 // for True
1 // for True

Lvalue, prvalue og xvalue

Tenk på følgende kode:

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

Utgangen er 35. I koden er ID og ID1 lValues ​​fordi de identifiserer et sted (objekt) i minnet. Utgangen 35 er en prvalue. Enhver bokstavelig, bortsett fra en streng bokstavelig, er en prvalue. Andre prvalues ​​er ikke så åpenbare, som i eksemplene som følger. Tenk på følgende kode:

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

PTR er en lValue fordi den identifiserer et sted (objekt) i minnet. På den annen side er ikke Pter en lValue. Pter er en peker, men den identifiserer ikke noe sted i minnet (den peker ikke på noe objekt). Så pter er en prvalue.

Tenk på følgende kode:

ugyldig fn ()

// uttalelser

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

Fn () og (*func) () er lValue -uttrykk fordi de identifiserer en enhet (funksjon) i minnet. På den annen side er (*functn) () ikke et LValue -uttrykk. (*functn) () er en peker til en funksjon, men den identifiserer ikke noen enhet i minnet (den peker ikke på noen funksjon i minnet). Så (*functn) () er et prvalue -uttrykk.

Vurder nå følgende kode:

struct s

int n;
;
S obj;

S er en klasse og OBJ er et objekt som er instantiert fra klassen. OBJ identifiserer et objekt i minnet. En klasse er en generalisert enhet. Så s identifiserer ikke noe objekt i minnet. S sies å være et navngitt objekt. S er også et prvalue -uttrykk.

Fokus for denne artikkelen er på prvalues. Prvalue betyr ren rvalue.

Xvalue

Xvalue står for utløpsverdi. Midlertidige verdier utløper verdier. En lValue kan bli en xvalue. En prvalue kan også bli en xvalue. Fokus for denne artikkelen er på prvalues. En xvalue er en lValue eller en ikke navngitt Rvalue -referanse hvis lagring kan gjenbrukes (vanligvis fordi den er nær slutten av levetiden). Tenk på følgende kode som fungerer:

struct s

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

Uttrykket “int q = s ().n; ” kopierer uansett verdi n har til q. S () er bare et middel; det er ikke et regelmessig brukt uttrykk. S () er en prvalue hvis bruk har konvertert den til en xvalue.

Lvalue-to-Rvalue-konverteringer

Tenk på følgende uttalelse:

int ii = 70;

70 er en prvalue (rvalue) og II er en lValue. Vurder nå følgende kode:

int ii = 70;
int tt = II;

I den andre uttalelsen er II i situasjonen til en prvalue, så II blir en prvalue der. Med andre ord konverterer kompilatoren II til en prvalue implisitt. Det vil si at når en lValue brukes i en situasjon der implementeringen forventer en prvalue, konverterer implementeringen Lvalue til en prvalue.

Array-to-Pointer-konverteringer

Tenk på følgende kode som fungerer:

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

Utgangen er b. Den første uttalelsen er et uttrykk og er en peker til en karakter. Men til hvilken karakter er uttalelsen som peker? - Ingen karakter. Så det er en prvalue og ikke en lValue. Den andre uttalelsen er en matrise der Q [] er et LValue -uttrykk. Den tredje uttalelsen gjør prvalue, p, til et Lvalue -uttrykk, som peker på det første elementet i matrisen.

Funksjon-til-peker konverteringer

Tenk på følgende program:

#inkludere
ved hjelp av navneområdet STD;
void (*func) ();
ugyldig fn ()

// uttalelser

int main ()

func = &fn;
retur 0;

Uttrykket “void (*func) ();” er en peker til en funksjon. Men til hvilken funksjon er uttrykket som peker? - Ingen funksjon. Så det er en prvalue og ikke en lValue. Fn () er en funksjonsdefinisjon, der FN er et LValue -uttrykk. I Main (), “func = &fn;”Gjør prvalue, func, til et Lvalue -uttrykk som peker på funksjonen, FN ().

Midlertidige materialiseringskonverteringer

I C ++ kan en prvalue konverteres til en xvalue av samme type. Følgende kode illustrerer dette:

struct s

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

Her er prvalue, s (), blitt konvertert til en xvalue. Som en xvalue ville det ikke vare lenge - se mer forklaring ovenfor.

Kvalifikasjonskonverteringer

En CV-kvalifisert type er en type som er kvalifisert av det reserverte ordet, “const” og/eller det reserverte ordet, “flyktig.”

CV-kvalifisering er også rangert. Ingen CV-kvalifisering er mindre enn "const" kvalifisering, som er mindre enn "const ustabil" kvalifisering. Ingen CV-kvalifisering er mindre enn "ustabil" kvalifisering, som er mindre enn "const ustabil" kvalifisering. Så det er to strømmer av kvalifiseringsrangering. En type kan være mer CV-kvalifisert enn en annen.

En lavere prvalue CV-kvalifisert type kan konverteres til en mer CV-kvalifisert prvalue-type. Begge typene skal være peker-til-CV.

Konklusjon

C ++ enheter kan konverteres fra en type til en relatert type implisitt eller eksplisitt. Programmereren må imidlertid forstå hva som kan konverteres og hva som ikke kan konverteres, og til hvilken form. Konvertering kan finne sted i følgende domener: Integrerte konverteringer, flytende punktkonverteringer, flytende integrale konverteringer, vanlige aritmetiske konverteringer, pekerkonverteringer, funksjon til pekerkonverteringer, boolske konverteringer, lvalue-til-rvalue-konverteringer, matrise-til-peker-konverteringer , Funksjon-til-peker konverteringer, midlertidige materialiseringskonverteringer og kvalifiseringskonverteringer.