Zoeken…


Char is mogelijk niet ondertekend of ondertekend

De standaard geeft niet aan of char moet worden ondertekend of niet ondertekend. Verschillende compilers implementeren het anders of kunnen het mogelijk maken om het te wijzigen met behulp van een opdrachtregelschakelaar.

Grootte van integrale typen

De volgende typen worden gedefinieerd als integrale typen :

  • char
  • Getekende integertypen
  • Niet-ondertekende gehele getallen
  • char16_t en char32_t
  • bool
  • wchar_t

Met uitzondering van sizeof(char) / sizeof(signed char) / sizeof(unsigned char) , die is verdeeld tussen § 3.9.1.1 [basic.fundamental / 1] en § 5.3.3.1 [expr.sizeof], en sizeof(bool) , die volledig door de implementatie is gedefinieerd en geen minimumgrootte heeft, worden de minimale groottevereisten van deze typen gegeven in sectie § 3.9.1 [basic.fundamental] van de norm, en worden hieronder gedetailleerd beschreven.

Grootte van char

Alle versies van de C ++ standaard specificeren, in § 5.3.3.1, dat sizeof 1 oplevert voor unsigned char , signed char en char (het is door de implementatie bepaald of het char is signed of unsigned is signed ).

C ++ 14

char is groot genoeg om 256 verschillende waarden weer te geven, geschikt voor het opslaan van UTF-8 code-eenheden.

Grootte van ondertekende en niet-ondertekende gehele getallen

De standaard specificeert, in § 3.9.1.2, dat in de lijst met standaard ondertekende integer-typen , bestaande uit signed char , short int , int , long int en long long int , elk type minstens evenveel opslagruimte biedt als de voorgaande het in de lijst. Bovendien, zoals gespecificeerd in § 3.9.1.3, heeft elk van deze types een overeenkomstig standaard niet-ondertekend geheel getal , unsigned char , unsigned short int , unsigned int , unsigned long int en unsigned long long int , die dezelfde grootte en uitlijning heeft als het bijbehorende ondertekende type. Bovendien, zoals gespecificeerd in § 3.9.1.1, heeft char dezelfde grootte- en uitlijningsvereisten als zowel signed char als unsigned char .

C ++ 11

Vóór C ++ 11 maakten long long en unsigned long long officieel geen deel uit van de C ++ standaard. Na hun introductie in C, in C99, ondersteunden veel compilers echter long long als een uitgebreid ondertekend geheel getal , en unsigned long long als een uitgebreid niet-ondertekend geheel getal , met dezelfde regels als de C-typen.

De norm garandeert dus dat:

1 == sizeof(char)  == sizeof(signed char) == sizeof(unsigned char)
  <= sizeof(short) == sizeof(unsigned short)
  <= sizeof(int)   == sizeof(unsigned int)
  <= sizeof(long)  == sizeof(unsigned long)
C ++ 11
 <= sizeof(long long) == sizeof(unsigned long long)

Specifieke minimummaten voor elk type worden niet door de standaard gegeven. In plaats daarvan heeft elk type een minimumbereik dat het kan ondersteunen, dat, zoals gespecificeerd in § 3.9.1.3, is overgenomen van de C-norm, in §5.2.4.2.1. De minimale grootte van elk type kan ruwweg worden afgeleid uit dit bereik, door het minimum aantal benodigde bits te bepalen; merk op dat voor elk gegeven platform het daadwerkelijke ondersteunde bereik van elk type groter kan zijn dan het minimum. Merk op dat voor ondertekende typen bereiken overeenkomen met iemands complement, niet het meer algemeen gebruikte twee-complement; dit om een breder scala aan platforms te laten voldoen aan de norm.

Type Minimum bereik Minimale bits vereist
signed char -127 tot 127 (- (2 7 - 1) tot (2 7 - 1)) 8
unsigned char 0 tot 255 (0 tot 2 8 - 1) 8
signed short -32.767 tot 32.767 (- (2 15 - 1) tot (2 15 - 1)) 16
unsigned short 0 tot 65.535 (0 tot 2 16 - 1) 16
signed int -32.767 tot 32.767 (- (2 15 - 1) tot (2 15 - 1)) 16
unsigned int 0 tot 65.535 (0 tot 2 16 - 1) 16
signed long -2.147.483.647 tot 2.147.483.647 (- (2 31 - 1) tot (2 31 - 1)) 32
unsigned long 0 tot 4.294.967.295 (0 tot 2 32 - 1) 32
C ++ 11
Type Minimum bereik Minimale bits vereist
signed long long -9.223.372.036.854.775.807 tot 9.223.372.036.854.775.807 (- (2 63 - 1) tot (2 63 - 1)) 64
unsigned long long 0 tot 18.446.744.073.709.551.615 (0 tot 2 64 - 1) 64

Omdat elk type groter mag zijn dan de minimale vereiste grootte, kunnen typen verschillen in implementaties. Het meest opvallende voorbeeld hiervan is met de 64-bit datamodellen LP64 en LLP64, waarbij LLP64-systemen (zoals 64-bit Windows) 32-bit ints en long s hebben, en LP64-systemen (zoals 64-bit Linux) hebben 32-bit int s en 64-bit long s. Hierdoor kan niet worden aangenomen dat gehele typen een vaste breedte hebben voor alle platforms.

C ++ 11

Als <cstdint> met vaste breedte vereist zijn, gebruikt u types uit de kop <cstdint> , maar <cstdint> rekening mee dat de standaard het voor implementaties optioneel maakt om de exact-breedte types int8_t , int16_t , int32_t , int64_t , intptr_t , uint8_t , uint16_t , uint32_t , uint64_t en uintptr_t .

C ++ 11

Grootte van char16_t en char32_t

De maten van char16_t en char32_t zijn implementatiegedefinieerd, zoals gespecificeerd in § 5.3.3.1, met de bepalingen in § 3.9.1.5:

  • char16_t is groot genoeg om elke UTF-16-code-eenheid te vertegenwoordigen en heeft dezelfde grootte, signatuur en uitlijning als uint_least16_t ; het moet dus minimaal 16 bits groot zijn.

  • char32_t is groot genoeg om elke UTF-32-code-eenheid te vertegenwoordigen en heeft dezelfde grootte, signatuur en uitlijning als uint_least32_t ; het moet dus minimaal 32 bits groot zijn.

Grootte van de bool

De grootte van bool is door de implementatie bepaald en kan al dan niet 1 .

Grootte van wchar_t

wchar_t , zoals gespecificeerd in § 3.9.1.5, is een verschillend type, waarvan het bereik van waarden elke afzonderlijke code-eenheid van de grootste uitgebreide tekenset onder de ondersteunde landinstellingen kan vertegenwoordigen. Het heeft dezelfde grootte, signatuur en uitlijning als een van de andere integrale typen, ook wel het onderliggende type genoemd . De grootte van dit type is door de implementatie bepaald, zoals gespecificeerd in § 5.3.3.1, en kan bijvoorbeeld minstens 8, 16 of 32 bits zijn; Als een systeem bijvoorbeeld Unicode ondersteunt, moet wchar_t minimaal 32 bits zijn (een uitzondering op deze regel is Windows, waarbij wchar_t 16 bits is voor compatibiliteitsdoeleinden). Het is geërfd van de C90-norm, ISO 9899: 1990, § 4.1.5, met slechts een kleine herformulering.

Afhankelijk van de implementatie is de grootte van wchar_t vaak, maar niet altijd, 8, 16 of 32 bits. De meest voorkomende voorbeelden hiervan zijn:

  • In Unix- en Unix-achtige systemen is wchar_t 32-bit en wordt meestal gebruikt voor UTF-32.
  • In Windows is wchar_t 16-bit en wordt het gebruikt voor UTF-16.
  • Op een systeem dat alleen 8-bit ondersteuning heeft, is wchar_t 8 bit.
C ++ 11

Als Unicode-ondersteuning gewenst is, wordt het aanbevolen om char te gebruiken voor UTF-8, char16_t voor UTF-16 of char32_t voor UTF-32, in plaats van wchar_t .


Gegevensmodellen

Zoals hierboven vermeld, kunnen de breedten van gehele typen tussen platforms verschillen. De meest voorkomende modellen zijn als volgt, met maten gespecificeerd in bits:

Model int long wijzer
LP32 (2/4/4) 16 32 32
ILP32 (4/4/4) 32 32 32
LLP64 (4/4/8) 32 32 64
LP64 (4/8/8) 32 64 64

Van deze modellen:

  • 16-bit Windows gebruikte LP32.
  • 32-bit * nix-systemen (Unix, Linux, Mac OSX en andere Unix-achtige besturingssystemen) en Windows gebruiken ILP32.
  • 64-bit Windows gebruikt LLP64.
  • 64-bit * nix-systemen gebruiken LP64.

Merk echter op dat deze modellen niet specifiek in de norm zelf worden vermeld.

Aantal bits in een byte

In C ++ is een byte de ruimte die wordt ingenomen door een char object. Het aantal bits in een byte wordt gegeven door CHAR_BIT , die wordt gedefinieerd in climits en minimaal 8 moet zijn. Hoewel de meeste moderne systemen 8-bits bytes hebben en POSIX vereist dat CHAR_BIT exact 8 is, zijn er enkele systemen waarbij CHAR_BIT groter is dan 8, dwz dat een enkele byte uit 8, 16, 32 of 64 bits kan bestaan.

Numerieke waarde van een aanwijzer

Het resultaat van het casten van een pointer naar een geheel getal met reinterpret_cast is door de implementatie gedefinieerd, maar "... is bedoeld als niet verrassend voor degenen die de adresstructuur van de onderliggende machine kennen."

int x = 42;
int* p = &x;
long addr = reinterpret_cast<long>(p);
std::cout << addr << "\n"; // prints some numeric address,
                           // probably in the architecture's native address format

Evenzo is de aanwijzer verkregen door conversie van een geheel getal ook door de implementatie gedefinieerd.

De juiste manier om een aanwijzer als een geheel getal op te slaan, is met de typen uintptr_t of intptr_t :

// `uintptr_t` was not in C++03. It's in C99, in <stdint.h>, as an optional type
#include <stdint.h>

uintptr_t uip;
C ++ 11
// There is an optional `std::uintptr_t` in C++11
#include <cstdint>

std::uintptr_t uip;

C ++ 11 verwijst naar C99 voor de definitie uintptr_t (C99 standaard, 6.3.2.3):

een geheel getal zonder teken met de eigenschap dat elke geldige aanwijzer naar void kan worden geconverteerd naar dit type en vervolgens weer kan worden geconverteerd naar aanwijzer naar void , en het resultaat wordt vergeleken met de oorspronkelijke aanwijzer.

Hoewel je voor de meeste moderne platforms kunt uitgaan van een platte adresruimte en dat rekenkunde op uintptr_t gelijk is aan rekenkunde op char * , is het heel goed mogelijk dat een implementatie een transformatie uitvoert bij het casten van void * naar uintptr_t zolang de transformatie kan worden teruggedraaid bij het terugdraaien van uintptr_t naar void * .

formaliteiten

  • Op XSI-conforme (X / Open System Interfaces) systemen zijn de intptr_t en uintptr_t vereist, anders zijn ze optioneel .

  • In de zin van de C-norm zijn functies geen objecten; door de C-standaard wordt niet gegarandeerd dat uintptr_t een uintptr_t kan bevatten. In elk geval vereist conformiteit van POSIX (2.12.3) dat:

    Alle typen functiewijzer moeten dezelfde weergave hebben als de te wissen typewijzer. Conversie van een functiepointer naar ongeldig * verandert niets aan de weergave. Een lege waarde * die het resultaat is van een dergelijke conversie, kan worden teruggezet naar het oorspronkelijke functiepointertype, met behulp van een expliciete cast, zonder verlies van informatie.

  • C99 §7.18.1:

    Wanneer typefefnamen die alleen verschillen in afwezigheid of aanwezigheid van de initiële u worden gedefinieerd, zullen zij overeenkomstige ondertekende en niet-ondertekende typen aanduiden zoals beschreven in 6.2.5; een implementatie die een van deze overeenkomstige typen biedt, moet ook de andere bieden.

    uintptr_t kan zinvol zijn als u dingen wilt doen met de bits van de aanwijzer die u niet zo verstandig kunt doen met een geheel getal met teken.

Bereik van numerieke typen

De bereiken van de typen integer zijn door de implementatie bepaald. De header <limits> biedt de sjabloon std::numeric_limits<T> die de minimum- en maximumwaarden van alle fundamentele typen biedt. De waarden voldoen aan de garanties die door de C-norm worden geboden via de <climits> en (> = C ++ 11) <cinttypes> headers.

  • std::numeric_limits<signed char>::min() gelijk aan SCHAR_MIN , die kleiner is dan of gelijk is aan -127.
  • std::numeric_limits<signed char>::max() gelijk aan SCHAR_MAX , dat groter is dan of gelijk is aan 127.
  • std::numeric_limits<unsigned char>::max() gelijk aan UCHAR_MAX , dat groter is dan of gelijk aan 255.
  • std::numeric_limits<short>::min() gelijk aan SHRT_MIN , dat kleiner is dan of gelijk is aan -32767.
  • std::numeric_limits<short>::max() gelijk aan SHRT_MAX , dat groter is dan of gelijk is aan 32767.
  • std::numeric_limits<unsigned short>::max() gelijk aan USHRT_MAX , dat groter is dan of gelijk is aan 65535.
  • std::numeric_limits<int>::min() gelijk aan INT_MIN , dat kleiner is dan of gelijk is aan -32767.
  • std::numeric_limits<int>::max() gelijk aan INT_MAX , dat groter is dan of gelijk is aan 32767.
  • std::numeric_limits<unsigned int>::max() gelijk aan UINT_MAX , dat groter is dan of gelijk is aan 65535.
  • std::numeric_limits<long>::min() gelijk aan LONG_MIN , dat kleiner is dan of gelijk is aan -2147483647.
  • std::numeric_limits<long>::max() gelijk aan LONG_MAX , dat groter is dan of gelijk is aan 2147483647.
  • std::numeric_limits<unsigned long>::max() gelijk aan ULONG_MAX , dat groter is dan of gelijk is aan 4294967295.
C ++ 11
  • std::numeric_limits<long long>::min() gelijk aan LLONG_MIN , die kleiner is dan of gelijk is aan -9223372036854775807.
  • std::numeric_limits<long long>::max() gelijk aan LLONG_MAX , dat groter is dan of gelijk is aan 9223372036854775807.
  • std::numeric_limits<unsigned long long>::max() gelijk aan ULLONG_MAX , dat groter is dan of gelijk is aan 18446744073709551615.

Voor drijvende-komma types T , is max() de maximale eindige waarde, terwijl min() de minimale positieve genormaliseerde waarde is. Er zijn extra leden voorzien voor drijvende-komma-typen, die ook door de implementatie zijn gedefinieerd, maar voldoen aan bepaalde garanties die door de C-norm worden geboden via de kop <cfloat> .

  • De digits10 geeft het aantal decimale cijfers van precisie.
    • std::numeric_limits<float>::digits10 gelijk aan FLT_DIG , wat ten minste 6 is.
    • std::numeric_limits<double>::digits10 gelijk aan DBL_DIG , wat ten minste 10 is.
    • std::numeric_limits<long double>::digits10 gelijk aan LDBL_DIG , wat ten minste 10 is.
  • Het lid min_exponent10 is de minimale negatieve E zodat 10 tot de macht E normaal is.
    • std::numeric_limits<float>::min_exponent10 gelijk aan FLT_MIN_10_EXP , wat maximaal -37 is.
    • std::numeric_limits<double>::min_exponent10 gelijk aan DBL_MIN_10_EXP , die maximaal -37 is. std::numeric_limits<long double>::min_exponent10 gelijk aan LDBL_MIN_10_EXP , die maximaal -37 is.
  • Het lid max_exponent10 is de maximale E zodat 10 tot de macht E eindig is.
    • std::numeric_limits<float>::max_exponent10 gelijk aan FLT_MIN_10_EXP , wat ten minste 37 is.
    • std::numeric_limits<double>::max_exponent10 gelijk aan DBL_MIN_10_EXP , wat ten minste 37 is.
    • std::numeric_limits<long double>::max_exponent10 gelijk aan LDBL_MIN_10_EXP , wat ten minste 37 is.
  • Als het lid is_iec559 waar is, voldoet het type aan IEC 559 / IEEE 754 en wordt het bereik daarom bepaald door die norm.

Waardeweergave van drijvende komma types

De norm vereist dat long double zo veel precisie biedt als double , wat minstens zo veel precisie biedt als float ; en dat een long double elke waarde kan vertegenwoordigen die een double kan vertegenwoordigen, terwijl een double elke waarde kan vertegenwoordigen die een float kan vertegenwoordigen. De details van de weergave zijn echter door de implementatie bepaald.

Voor een drijvend punt type T geeft std::numeric_limits<T>::radix de radix aan die wordt gebruikt door de weergave van T

Als std::numeric_limits<T>::is_iec559 waar is, komt de weergave van T overeen met een van de indelingen die zijn gedefinieerd door IEC 559 / IEEE 754.

Overloop bij conversie van geheel getal naar ondertekend geheel getal

Wanneer een ondertekend of niet-ondertekend geheel getal wordt geconverteerd naar een type met een ondertekend geheel getal en de waarde ervan niet kan worden weergegeven in het type bestemming, wordt de geproduceerde waarde door de implementatie bepaald. Voorbeeld:

// Suppose that on this implementation, the range of signed char is -128 to +127 and
// the range of unsigned char is 0 to 255
int x = 12345;
signed char sc = x;   // sc has an implementation-defined value
unsigned char uc = x; // uc is initialized to 57 (i.e., 12345 modulo 256)

Onderliggend type (en dus de grootte) van een opsomming

Als het onderliggende type niet expliciet is opgegeven voor een niet-gescandeerd opsommingstype, wordt het bepaald op een door de implementatie gedefinieerde manier.

enum E {
    RED,
    GREEN,
    BLUE,
};
using T = std::underlying_type<E>::type; // implementation-defined

De standaard vereist echter dat het onderliggende type van een opsomming niet groter is dan int tenzij zowel int als unsigned int niet alle waarden van de opsomming kunnen weergeven. Daarom is in de bovenstaande code, T zou kunnen zijn int , unsigned int , of short , maar niet long long , om een paar voorbeelden te geven.

Merk op dat een opsomming dezelfde grootte heeft (zoals geretourneerd door sizeof ) als het onderliggende type.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow