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 och char32_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 )

C ++ 14

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 .

C ++ 11

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)
C ++ 11
 <= 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
C ++ 11
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.

C ++ 11

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 .

C ++ 11

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 som uint_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 som uint_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.
C ++ 11

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;
C ++ 11
// 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 till void , 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 och uintptr_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 med SCHAR_MIN , vilket är mindre än eller lika med -127.
  • std::numeric_limits<signed char>::max() lika med SCHAR_MAX , som är större än eller lika med 127.
  • std::numeric_limits<unsigned char>::max() lika med UCHAR_MAX , vilket är större än eller lika med 255.
  • std::numeric_limits<short>::min() lika med SHRT_MIN , vilket är mindre än eller lika med -32767.
  • std::numeric_limits<short>::max() lika med SHRT_MAX , vilket är större än eller lika med 32767.
  • std::numeric_limits<unsigned short>::max() lika med USHRT_MAX , vilket är större än eller lika med 65535.
  • std::numeric_limits<int>::min() lika med INT_MIN , vilket är mindre än eller lika med -32767.
  • std::numeric_limits<int>::max() lika med INT_MAX , vilket är större än eller lika med 32767.
  • std::numeric_limits<unsigned int>::max() lika med UINT_MAX , vilket är större än eller lika med 65535.
  • std::numeric_limits<long>::min() lika med LONG_MIN , vilket är mindre än eller lika med -2147483647.
  • std::numeric_limits<long>::max() är LONG_MAX , vilket är större än eller lika med 2147483647.
  • std::numeric_limits<unsigned long>::max() lika med ULONG_MAX , vilket är större än eller lika med 4294967295.
C ++ 11
  • std::numeric_limits<long long>::min() är LLONG_MIN , vilket är mindre än eller lika med -9223372036854775807.
  • std::numeric_limits<long long>::max() lika med LLONG_MAX , vilket är större än eller lika med 9223372036854775807.
  • std::numeric_limits<unsigned long long>::max() lika med ULLONG_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 med FLT_DIG , vilket är minst 6.
    • std::numeric_limits<double>::digits10 lika med DBL_DIG , vilket är minst 10.
    • std::numeric_limits<long double>::digits10 lika med LDBL_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 med FLT_MIN_10_EXP , vilket är högst -37.
    • std::numeric_limits<double>::min_exponent10 lika med DBL_MIN_10_EXP , som är högst -37. std::numeric_limits<long double>::min_exponent10 lika med LDBL_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 med FLT_MIN_10_EXP , vilket är minst 37.
    • std::numeric_limits<double>::max_exponent10 lika med DBL_MIN_10_EXP , vilket är minst 37.
    • std::numeric_limits<long double>::max_exponent10 lika med LDBL_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.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow