C++
Implementeringsdefinerat beteende
Sök…
Char kan vara osignerad eller signerad
Standarden anger inte om char ska vara signerad eller osignerad. Olika kompilatorer implementerar det annorlunda eller kan tillåta att ändra det med en kommandoradströmbrytare.
Storlek på integrerade typer
Följande typer definieras som integrerade typer :
-
char - Signerade heltalstyper
- Osignerade heltalstyper
-
char16_tochchar32_t -
bool -
wchar_t
Med undantag av sizeof(char) / sizeof(signed char) / sizeof(unsigned char) , som är uppdelat mellan § 3.9.1.1 [basic.fundamental / 1] och § 5.3.3.1 [expr.sizeof], och sizeof(bool) , som är helt implementeringsdefinierad och inte har någon minsta storlek, anges minimikraven för dessa typer i avsnitt § 3.9.1 [grundläggande.fundamental] i standarden och ska beskrivas nedan.
Storlek på char
Alla versioner av C ++ -standarden specificerar, i § 5.3.3.1, att sizeof ger 1 för unsigned char , signed char och char (det är implementeringen definierad om char är signed eller unsigned )
char är tillräckligt stor för att representera 256 olika värden, för att vara lämplig för lagring av UTF-8-kodenheter.
Storlek på signerade och osignerade heltalstyper
Standarden specificerar, i § 3.9.1.2, att i listan över standard signerade heltalstyper , bestående av signed char , short int , int , long int och long long int , kommer varje typ att ge minst lika stor lagring som de föregående det i listan. Som anges i § 3.9.1.3 har vardera av dessa typer en motsvarande standard osignerad heltalstyp , unsigned char , unsigned short int , unsigned int , unsigned long int , och unsigned long long int , som har samma storlek och justering som dess motsvarande signerade typ. Dessutom, som anges i § 3.9.1.1, char har samma storlek och justering krav som både signed char och unsigned char .
Innan C ++ 11 var long long och unsigned long long officiellt inte del av C ++ -standarden. Men efter deras introduktion till C, i C99, stödde många kompilatorer long long som en utökad signerad heltalstyp , och unsigned long long som en utvidgad osignerad heltalstyp , med samma regler som C-typerna.
Standarden garanterar således att:
1 == sizeof(char) == sizeof(signed char) == sizeof(unsigned char)
<= sizeof(short) == sizeof(unsigned short)
<= sizeof(int) == sizeof(unsigned int)
<= sizeof(long) == sizeof(unsigned long)
<= sizeof(long long) == sizeof(unsigned long long)
Specifika minimistorlekar för varje typ anges inte av standarden. Istället har varje typ ett minimivärde av värden som den kan stödja, vilket är, som anges i § 3.9.1.3, ärvt från C-standarden, i §5.2.4.2.1. Minsta storleken för varje typ kan sluts grovt från detta intervall genom att bestämma det minsta antalet bitar som krävs; Observera att för varje given plattform kan någon typens faktiska stödintervall vara större än minimum. Observera att för signerade typer motsvarar intervall ett komplement, inte det vanligaste två komplementet; detta för att tillåta ett större utbud av plattformar att följa standarden.
| Typ | Minsta intervall | Minsta bitar krävs |
|---|---|---|
signed char | -127 till 127 (- (2 7 - 1) till (2 7 - 1)) | 8 |
unsigned char | 0 till 255 (0 till 2 8 - 1) | 8 |
signed short | -32,767 till 32,767 (- (2 15 - 1) till (2 15 - 1)) | 16 |
unsigned short | 0 till 65,535 (0 till 2 16 - 1) | 16 |
signed int | -32,767 till 32,767 (- (2 15 - 1) till (2 15 - 1)) | 16 |
unsigned int | 0 till 65,535 (0 till 2 16 - 1) | 16 |
signed long | -2,147,483,647 till 2,147,483,647 (- (2 31 - 1) till (2 31 - 1)) | 32 |
unsigned long | 0 till 4 294 967 295 (0 till 2 32 - 1) | 32 |
| Typ | Minsta intervall | Minsta bitar krävs |
|---|---|---|
signed long long | -9,223,372,036,854,775,807 till 9,223,372,036,854,775,807 (- (2 63 - 1) till (2 63 - 1)) | 64 |
unsigned long long | 0 till 18.446.744.073.709.551.615 (0 till 2 64 - 1) | 64 |
Eftersom varje typ tillåts vara större än dess minimistorlek, kan typerna skilja sig i storlek mellan implementeringarna. Det mest anmärkningsvärda exemplet på detta är med 64-bitars datamodellerna LP64 och LLP64, där LLP64-system (som 64-bitars Windows) har 32-bitars ints och long s, och LP64-system (som 64-bitars Linux) har 32-bitars int och 64-bitars long . På grund av detta kan inte heltalstyper antas ha en fast bredd över alla plattformar.
Om heltalstyper med fast bredd krävs, använd typer från <cstdint> , men observera att standarden gör det frivilligt för implementeringar att stödja exakta int8_t , int16_t , int32_t , int64_t , intptr_t , uint8_t , uint16_t , uint32_t , uint64_t och uintptr_t .
Storlek på char16_t och char32_t
Storleken på char16_t och char32_t är implementeringsdefinerade, enligt specifikationerna i § 5.3.3.1, med bestämmelserna i § 3.9.1.5:
char16_tär tillräckligt stor för att representera alla UTF-16-kodenheter och har samma storlek, signatur och inriktning somuint_least16_t; det krävs således att det är minst 16 bitar i storlek.char32_tär tillräckligt stor för att representera alla UTF-32-kodenheter och har samma storlek, signatur och inriktning somuint_least32_t; det krävs således att vara minst 32 bitar i storlek.
Storlek på bool
Storleken på bool är implementeringsdefinierad och kan vara eller inte vara 1 .
Storlek på wchar_t
wchar_t , som specificeras i § 3.9.1.5, är en distinkt typ, vars värden kan representera varje distinkt kodenhet med den största utvidgade teckenuppsättningen bland de stöttade platserna. Den har samma storlek, signatur och anpassning som en av de andra integrerade typerna, som kallas dess underliggande typ . Denna typs storlek är implementeringsdefinierad, som specificeras i § 5.3.3.1, och kan till exempel vara minst 8, 16 eller 32 bitar; Om ett system till exempel stöder Unicode krävs det att wchar_t ska vara minst 32 bitar (ett undantag från denna regel är Windows, där wchar_t är 16 bitar för kompatibilitetsändamål). Den ärvs från C90-standarden, ISO 9899: 1990 § 4.1.5, med endast mindre omformulering.
Beroende på implementering är storleken på wchar_t ofta, men inte alltid, 8, 16 eller 32 bitar. De vanligaste exemplen på dessa är:
- I Unix och Unix-liknande system är
wchar_t32-bitars och används vanligtvis för UTF-32. - I Windows är
wchar_t16-bitars och används för UTF-16. - På ett system som bara har 8-bitars support är
wchar_t8 bit.
Om Unicode-stöd önskas rekommenderas det att använda char för UTF-8, char16_t för UTF-16 eller char32_t för UTF-32, istället för att använda wchar_t .
Datamodeller
Som nämnts ovan kan bredden på heltalstyper skilja sig mellan plattformar. De vanligaste modellerna är följande, med storlekar som anges i bitar:
| Modell | int | long | pekare |
|---|---|---|---|
| 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 |
Av dessa modeller:
- 16-bitars Windows använde LP32.
- 32-bitars * nix-system (Unix, Linux, Mac OSX och andra Unix-liknande operativsystem) och Windows använder ILP32.
- 64-bitars Windows använder LLP64.
- 64-bitars * nix-system använder LP64.
Observera dock att dessa modeller inte nämns specifikt i själva standarden.
Antal bitar i en byte
I C ++ är en byte det utrymme som upptas av ett char . Antalet bitar i en byte anges av CHAR_BIT , vilket definieras i climits och måste vara minst 8. Medan de flesta moderna system har 8-bitarsbyte, och POSIX kräver att CHAR_BIT är exakt 8, finns det några system där CHAR_BIT är större än 8, dvs. en enda byte kan bestå av 8, 16, 32 eller 64 bitar.
Numeriskt värde för en pekare
Resultatet av att kasta en pekare till ett heltal med reinterpret_cast är implementeringsdefinerat, men "... är avsett att vara överraskande för dem som känner adressstrukturen för den underliggande maskinen."
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
På samma sätt definieras även pekaren genom konvertering från ett heltal.
Det rätta sättet att lagra en pekare som ett heltal använder uintptr_t eller intptr_t typerna:
// `uintptr_t` was not in C++03. It's in C99, in <stdint.h>, as an optional type
#include <stdint.h>
uintptr_t uip;
// There is an optional `std::uintptr_t` in C++11
#include <cstdint>
std::uintptr_t uip;
C ++ 11 hänför sig till C99 för definitionen uintptr_t (C99-standard, 6.3.2.3):
en osignerad heltalstyp med den egenskapen som alla giltiga pekare som kan
voidkan konverteras till den här typen, sedan konverteras tillbaka till pekaren tillvoid, och resultatet kommer att jämföra lika med den ursprungliga pekaren.
Även om du för de flesta moderna plattformar kan anta ett platt adressutrymme och att aritmetik på uintptr_t motsvarar aritmetik på char * , är det fullt möjligt för en implementering att utföra någon transformation när man kastar void * till uintptr_t så länge transformationen kan vändas när du kastar tillbaka från uintptr_t till void * .
teknikaliteter
På XSI-överensstämmande (X / Open System Interfaces) -system
intptr_tochuintptr_ttyper, annars är de valfria .Enligt C-standarden är funktioner inte objekt; det är inte garanterat av C-standarden att
uintptr_tkan hålla en funktionspekare. Hur som helst POSIX (2.12.3) överensstämmelse kräver att:Alla funktionspekartyper ska ha samma representation som typen pekare som ska ogiltigförklaras. Omvandling av en funktionspekare till ogiltig * påverkar inte representationen. Ett tomrum * -värde som härrör från en sådan konvertering kan konverteras tillbaka till den ursprungliga funktionen pekartyp, med hjälp av en uttrycklig roll, utan förlust av information.
C99 §7.18.1:
När typedef-namn som endast skiljer sig i frånvaro eller närvaro av den initiala u definieras, ska de beteckna motsvarande signerade och osignerade typer som beskrivs i 6.2.5; en implementering som tillhandahåller en av dessa motsvarande typer ska också tillhandahålla den andra.
uintptr_tkan vara meningsfullt om du vill göra saker till pekarens bitar som du inte kan göra så förnuftigt med ett signerat heltal.
Antal numeriska typer
Områdena för heltalstyperna är implementeringsdefinerade. Rubriken <limits> tillhandahåller std::numeric_limits<T> -mallen som ger minimi- och maximivärden för alla grundläggande typer. Värdena uppfyller de garantier som tillhandahålls av C-standarden genom <climits> och (> = C ++ 11) <cinttypes> rubriker.
-
std::numeric_limits<signed char>::min()lika medSCHAR_MIN, vilket är mindre än eller lika med -127. -
std::numeric_limits<signed char>::max()lika medSCHAR_MAX, som är större än eller lika med 127. -
std::numeric_limits<unsigned char>::max()lika medUCHAR_MAX, vilket är större än eller lika med 255. -
std::numeric_limits<short>::min()lika medSHRT_MIN, vilket är mindre än eller lika med -32767. -
std::numeric_limits<short>::max()lika medSHRT_MAX, vilket är större än eller lika med 32767. -
std::numeric_limits<unsigned short>::max()lika medUSHRT_MAX, vilket är större än eller lika med 65535. -
std::numeric_limits<int>::min()lika medINT_MIN, vilket är mindre än eller lika med -32767. -
std::numeric_limits<int>::max()lika medINT_MAX, vilket är större än eller lika med 32767. -
std::numeric_limits<unsigned int>::max()lika medUINT_MAX, vilket är större än eller lika med 65535. -
std::numeric_limits<long>::min()lika medLONG_MIN, vilket är mindre än eller lika med -2147483647. -
std::numeric_limits<long>::max()ärLONG_MAX, vilket är större än eller lika med 2147483647. -
std::numeric_limits<unsigned long>::max()lika medULONG_MAX, vilket är större än eller lika med 4294967295.
-
std::numeric_limits<long long>::min()ärLLONG_MIN, vilket är mindre än eller lika med -9223372036854775807. -
std::numeric_limits<long long>::max()lika medLLONG_MAX, vilket är större än eller lika med 9223372036854775807. -
std::numeric_limits<unsigned long long>::max()lika medULLONG_MAX, vilket är större än eller lika med 18446744073709551615.
För flytande punkttyper T är max() det maximala slutliga värdet medan min() är det minsta positiva normaliserade värdet. Ytterligare medlemmar tillhandahålls för flytande punkttyper, som också är implementeringsdefinierade men uppfyller vissa garantier som tillhandahålls av C-standarden via <cfloat> .
-
digits10ger antalet decimaler med precision.-
std::numeric_limits<float>::digits10lika medFLT_DIG, vilket är minst 6. -
std::numeric_limits<double>::digits10lika medDBL_DIG, vilket är minst 10. -
std::numeric_limits<long double>::digits10lika medLDBL_DIG, vilket är minst 10.
-
-
min_exponent10är det minsta negativa E så att 10 till effekten E är normalt.-
std::numeric_limits<float>::min_exponent10lika medFLT_MIN_10_EXP, vilket är högst -37. -
std::numeric_limits<double>::min_exponent10lika medDBL_MIN_10_EXP, som är högst -37.std::numeric_limits<long double>::min_exponent10lika medLDBL_MIN_10_EXP, vilket är högst -37.
-
-
max_exponent10är det maximala E så att 10 till effekten E är begränsat.-
std::numeric_limits<float>::max_exponent10lika medFLT_MIN_10_EXP, vilket är minst 37. -
std::numeric_limits<double>::max_exponent10lika medDBL_MIN_10_EXP, vilket är minst 37. -
std::numeric_limits<long double>::max_exponent10lika medLDBL_MIN_10_EXP, vilket är minst 37.
-
- Om medlemmet
is_iec559är sant, överensstämmer typen med IEC 559 / IEEE 754, och dess intervall bestäms därför av denna standard.
Värde representation av flytande punkttyper
Standarden kräver att long double ger minst lika mycket precision som double , vilket ger minst lika stor precision som float ; och att en long double kan representera vilket värde som en double kan representera, medan en double kan representera alla värden som en float kan representera. Detaljerna för representationen är emellertid implementeringsdefinerade.
För en flytande punkt typ T std::numeric_limits<T>::radix radix som används av representationen av T
Om std::numeric_limits<T>::is_iec559 är sant, matchar representationen av T ett av de format som definieras av IEC 559 / IEEE 754.
Överflöde vid konvertering från heltal till signerat heltal
När antingen ett signerat eller osignerat heltal konverteras till en signerad heltalstyp, och dess värde inte kan representeras i destinationstypen, definieras värdet som implementeras. Exempel:
// 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)
Underliggande typ (och därmed storlek) av enum
Om den underliggande typen inte uttryckligen anges för en icke-kodad uppräkningstyp, bestäms den på ett implementeringsdefinerat sätt.
enum E {
RED,
GREEN,
BLUE,
};
using T = std::underlying_type<E>::type; // implementation-defined
Men standarden kräver att den underliggande typen av en uppräkning inte är större än int inte både int och unsigned int inte kan representera alla värdena för uppräkningen. I koden ovan kan T därför vara int , unsigned int eller short , men inte long long att ge några exempel.
Observera att en enum har samma storlek (som returneras av sizeof ) som dess underliggande typ.