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_t
ochchar32_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_t
32-bitars och används vanligtvis för UTF-32. - I Windows är
wchar_t
16-bitars och används för UTF-16. - På ett system som bara har 8-bitars support är
wchar_t
8 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
void
kan 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_t
ochuintptr_t
typer, annars är de valfria .Enligt C-standarden är funktioner inte objekt; det är inte garanterat av C-standarden att
uintptr_t
kan 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_t
kan 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>
.
-
digits10
ger antalet decimaler med precision.-
std::numeric_limits<float>::digits10
lika medFLT_DIG
, vilket är minst 6. -
std::numeric_limits<double>::digits10
lika medDBL_DIG
, vilket är minst 10. -
std::numeric_limits<long double>::digits10
lika 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_exponent10
lika medFLT_MIN_10_EXP
, vilket är högst -37. -
std::numeric_limits<double>::min_exponent10
lika medDBL_MIN_10_EXP
, som är högst -37.std::numeric_limits<long double>::min_exponent10
lika 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_exponent10
lika medFLT_MIN_10_EXP
, vilket är minst 37. -
std::numeric_limits<double>::max_exponent10
lika medDBL_MIN_10_EXP
, vilket är minst 37. -
std::numeric_limits<long double>::max_exponent10
lika 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.