Suche…


Char ist möglicherweise nicht signiert oder signiert

Der Standard gibt nicht an, ob char signiert oder nicht signiert sein soll. Verschiedene Compiler implementieren sie unterschiedlich oder erlauben es möglicherweise, sie mit einem Befehlszeilenschalter zu ändern.

Größe der ganzzahligen Typen

Die folgenden Typen sind als integrale Typen definiert:

  • char
  • Signierte Integer-Typen
  • Vorzeichenlose Integer-Typen
  • char16_t und char32_t
  • bool
  • wchar_t

Mit Ausnahme von sizeof(char) / sizeof(signed char) / sizeof(unsigned char) Zeichen sizeof(unsigned char) , das sich in § 3.9.1.1 [basic.fundamental / 1] und § 5.3.3.1 [expr.sizeof] und sizeof(bool) , das vollständig implementierungsdefiniert ist und keine Mindestgröße hat, sind die Mindestgrößenanforderungen dieser Typen in Abschnitt 3.9.1 [basic.fundamental] der Norm angegeben und werden im Folgenden detailliert beschrieben.

Größe des char

Alle Versionen des C ++ Standard angeben, in § 5.3.3.1, dass sizeof Ausbeuten 1 für unsigned char , signed char und char (es ist festgelegt , ob die Umsetzung char Typ wird signed oder unsigned ).

C ++ 14

char ist groß genug, um 256 verschiedene Werte darzustellen, um UTF-8-Codeeinheiten speichern zu können.

Größe der vorzeichenbehafteten und vorzeichenlosen Integer-Typen

Der Standard legt in § 3.9.1.2 fest, dass jeder Typ in der Liste der signierten Integer-Typen mit Vorzeichen , bestehend aus signed char , short int , int , long int und long long int , mindestens so viel Speicherplatz bereitstellen wird wie die vorhergehenden es in der Liste. Wie in § 3.9.1.3 angegeben, hat jeder dieser Typen außerdem einen entsprechenden vorzeichenlosen Integer-Typ mit unsigned char , unsigned char , unsigned short int , unsigned int , unsigned long int und ein unsigned long long int , das dieselbe Größe und Ausrichtung wie hat der entsprechende signierte Typ. Gemäß § 3.9.1.1 hat char die gleichen Größen- und Ausrichtungsanforderungen wie signed char und unsigned char .

C ++ 11

long long und unsigned long long waren vor C ++ 11 nicht offiziell Teil des C ++ - Standards. Nach der Einführung von C in C99 unterstützten viele Compiler jedoch den long long Typ als Ganzzahl mit unsigned long long und den unsigned long long als unsigned long long Ganzzahl mit Vorzeichen und den gleichen Regeln wie die C-Typen.

Der Standard garantiert somit:

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)

Bestimmte Mindestgrößen für jeden Typ sind in der Norm nicht angegeben. Stattdessen verfügt jeder Typ über einen minimalen Wertebereich, den er unterstützen kann. Dieser wird, wie in § 3.9.1.3 angegeben, vom C-Standard in §5.2.4.2.1 übernommen. Die Mindestgröße jedes Typs kann grob aus diesem Bereich abgeleitet werden, indem die erforderliche Mindestanzahl von Bits bestimmt wird. Beachten Sie, dass für jede Plattform der tatsächlich unterstützte Bereich eines Typs größer sein kann als das Minimum. Beachten Sie, dass die Bereiche für vorzeichenbehaftete Typen einem Komplement entsprechen, nicht dem am häufigsten verwendeten Zweierkomplement; Dies ermöglicht eine breitere Palette von Plattformen, um den Standard zu erfüllen.

Art Mindestbereich Minimale Bits erforderlich
signed char -127 bis 127 (- (2 7 - 1) bis (2 7 - 1)) 8
unsigned char 0 bis 255 (0 bis 2 8 - 1) 8
signed short -32,767 bis 32,767 (- (2 15 - 1) bis (2 15 - 1)) 16
unsigned short 0 bis 65.535 (0 bis 2 16 - 1) 16
signed int -32,767 bis 32,767 (- (2 15 - 1) bis (2 15 - 1)) 16
unsigned int 0 bis 65.535 (0 bis 2 16 - 1) 16
signed long -2147483647 bis 2.147.483.647 (- (Februar 31-01) bis (31-01 Februar)) 32
unsigned long 0 bis 4.294.967.295 (0 bis 2 32 - 1) 32
C ++ 11
Art Mindestbereich Minimale Bits erforderlich
signed long long -9.223.372.036.854.775.807 zu 9,223,372,036,854,775,807 (- (2 63 - 1) bis (2 63 - 1)) 64
unsigned long long 0 bis 18.446.744.073.709.551.615 (0 bis 2 64 - 1) 64

Da jeder Typ größer sein darf als seine Mindestgröße, können sich die Typen zwischen den Implementierungen unterscheiden. Das bemerkenswerteste Beispiel hierfür ist mit den 64-Bit - Datenmodellen LP64 und LLP64, wo LLP64 Systeme (wie 64-Bit - Windows) 32-Bit ints und long s und LP64 - Systeme (wie 64-Bit - Linux) haben 32-Bit - int s und 64-Bit long s. Daher kann für Integer-Typen nicht angenommen werden, dass sie auf allen Plattformen eine feste Breite haben.

C ++ 11

Wenn ganzzahlige Typen mit fester Breite erforderlich sind, verwenden Sie Typen aus dem Header <cstdint> Beachten Sie jedoch, dass der Standard es für Implementierungen optional macht, die Typen mit exakter Breite int8_t , int16_t , int32_t , int64_t , intptr_t , uint8_t , uint16_t , uint32_t , uint64_t und uintptr_t .

C ++ 11

Größe von char16_t und char32_t

Die Größen von char16_t und char32_t sind implementierungsdefiniert, wie in § 5.3.3.1 angegeben, mit den in § 3.9.1.5 angegebenen Bestimmungen:

  • char16_t ist groß genug, um eine beliebige UTF-16-Codeeinheit darzustellen, und hat dieselbe Größe, Vorzeichen und Ausrichtung wie uint_least16_t ; es muss daher mindestens 16 Bit groß sein.

  • char32_t ist groß genug, um eine beliebige UTF-32-Codeeinheit darzustellen, und hat dieselbe Größe, Vorzeichen und Ausrichtung wie uint_least32_t ; es muss daher mindestens 32 Bit groß sein.

Größe des bool

Die Größe von bool ist durch die Implementierung definiert und kann 1 sein oder nicht.

Größe von wchar_t

wchar_t , wie in § 3.9.1.5 angegeben, ein eindeutiger Typ, dessen Wertebereich jede unterschiedliche Codeeinheit des größten erweiterten Zeichensatzes unter den unterstützten Gebietsschemas darstellen kann. Es hat die gleiche Größe, Vorzeichen und Ausrichtung wie ein anderer integraler Typ, der als zugrunde liegender Typ bezeichnet wird . Die Größe dieses Typs ist implementierungsdefiniert, wie in § 5.3.3.1 angegeben, und kann beispielsweise mindestens 8, 16 oder 32 Bit betragen. Wenn ein System Unicode unterstützt, muss wchar_t beispielsweise mindestens 32 Bit umfassen (eine Ausnahme von dieser Regel ist Windows, wobei wchar_t aus Kompatibilitätsgründen 16 Bit beträgt). Es ist vom Standard C90, ISO 9899: 1990 § 4.1.5, mit nur geringfügigen Umformungen vererbt.

Je nach Implementierung beträgt die Größe von wchar_t oft, aber nicht immer 8, 16 oder 32 Bit. Die häufigsten Beispiele dafür sind:

  • In Unix- und Unix-ähnlichen Systemen ist wchar_t 32-Bit und wird normalerweise für UTF-32 verwendet.
  • In Windows ist wchar_t 16-Bit und wird für UTF-16 verwendet.
  • Auf einem System, das nur 8-Bit-Unterstützung bietet, ist wchar_t 8 Bit.
C ++ 11

Wenn Unicode-Unterstützung gewünscht wird, wird empfohlen, char für UTF-8, char16_t für UTF-16 oder char32_t für UTF-32 zu verwenden, anstatt wchar_t .


Datenmodelle

Wie bereits erwähnt, können die Breiten von Integertypen zwischen Plattformen variieren. Die gebräuchlichsten Modelle sind folgende, wobei die Größen in Bits angegeben sind:

Modell int long Zeiger
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

Von diesen Modellen:

  • 16-Bit-Windows verwendete LP32.
  • 32-Bit * Nix-Systeme (Unix, Linux, Mac OSX und andere Unix-ähnliche Betriebssysteme) und Windows verwenden ILP32.
  • 64-Bit-Windows verwendet LLP64.
  • 64-Bit * Nix-Systeme verwenden LP64.

Beachten Sie jedoch, dass diese Modelle im Standard selbst nicht ausdrücklich erwähnt werden.

Anzahl der Bits in einem Byte

In C ++ ist ein Byte der von einem char Objekt belegte Platz. Die Anzahl der Bits in einem Byte wird durch CHAR_BIT , das in climits definiert climits und mindestens 8 climits muss. Während die meisten modernen Systeme 8-Bit-Bytes aufweisen und für POSIX CHAR_BIT genau 8 ist, gibt es einige Systeme, bei denen CHAR_BIT ist größer als 8, dh ein einzelnes Byte kann aus 8, 16, 32 oder 64 Bits bestehen.

Numerischer Wert eines Zeigers

Das Ergebnis des Umsetzens eines Zeigers auf eine Ganzzahl mit reinterpret_cast ist implementierungsdefiniert, aber "... soll für diejenigen nicht überraschend sein, die die Adressierungsstruktur des zugrunde liegenden Computers 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

Ebenso ist der durch Konvertierung aus einer Ganzzahl erhaltene Zeiger implementierungsdefiniert.

uintptr_t einen Zeiger als Ganzzahl zu speichern, verwenden Sie die Typen uintptr_t oder 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 bezieht sich auf C99 für die Definition uintptr_t (C99-Standard, 6.3.2.3):

ein vorzeichenloser Integer-Typ mit der Eigenschaft, dass ein beliebiger gültiger Zeiger auf void in diesen Typ konvertiert und dann wieder in einen Zeiger auf void konvertiert void kann und das Ergebnis dem ursprünglichen Zeiger entspricht.

Während für die meisten modernen Plattformen ein flacher Adressraum angenommen werden kann und die Arithmetik bei uintptr_t der Arithmetik bei char * , ist es durchaus möglich, dass eine Implementierung jede Transformation ausführt, wenn void * in uintptr_t , solange die Transformation dies kann Umkehrung beim uintptr_t von uintptr_t nach void * .

Technische Aspekte

  • Bei XSI-konformen Systemen (X / Open System Interfaces) sind die Typen intptr_t und uintptr_t erforderlich. Andernfalls sind sie optional .

  • Funktionen im Sinne des C-Standards sind keine Objekte; Der C-Standard garantiert nicht, dass uintptr_t einen Funktionszeiger uintptr_t kann. Die Konformität von POSIX (2.12.3) erfordert jedoch Folgendes:

    Alle Funktionszeigertypen müssen dieselbe Darstellung wie der Typzeiger auf void haben. Die Umwandlung eines Funktionszeigers in void * ändert nichts an der Darstellung. Ein void * -Wert, der sich aus einer solchen Konvertierung ergibt, kann mithilfe einer expliziten Umwandlung ohne Informationsverlust in den ursprünglichen Funktionszeigertyp konvertiert werden.

  • C99 §7.18.1:

    Wenn Typedef-Namen definiert werden, die sich nur in Abwesenheit oder Vorhandensein des anfänglichen u unterscheiden, müssen sie entsprechend vorzeichenbehaftete und vorzeichenlose Typen angeben, wie in 6.2.5 beschrieben. Eine Implementierung, die einen dieser entsprechenden Typen bereitstellt, muss auch den anderen bereitstellen.

    uintptr_t kann sinnvoll sein, wenn Sie Dinge mit den Bits des Zeigers machen möchten, die Sie mit einer vorzeichenbehafteten Ganzzahl nicht so sinnvoll uintptr_t können.

Bereiche numerischer Typen

Die Bereiche der Integer-Typen sind implementierungsdefiniert. Der Header <limits> enthält die Vorlage std::numeric_limits<T> die die Minimal- und Maximalwerte aller grundlegenden Typen std::numeric_limits<T> . Die Werte erfüllen die Garantien, die der C-Standard durch die <climits> und (> = C ++ 11) <cinttypes> .

  • std::numeric_limits<signed char>::min() entspricht SCHAR_MIN , was kleiner oder gleich -127 ist.
  • std::numeric_limits<signed char>::max() entspricht SCHAR_MAX , der größer oder gleich 127 ist.
  • std::numeric_limits<unsigned char>::max() entspricht UCHAR_MAX , der größer als oder gleich 255 ist.
  • std::numeric_limits<short>::min() entspricht SHRT_MIN , was kleiner oder gleich -32767 ist.
  • std::numeric_limits<short>::max() entspricht SHRT_MAX , was größer oder gleich 32767 ist.
  • std::numeric_limits<unsigned short>::max() entspricht USHRT_MAX , der größer als oder gleich 65535 ist.
  • std::numeric_limits<int>::min() entspricht INT_MIN , was kleiner oder gleich -32767 ist.
  • std::numeric_limits<int>::max() entspricht INT_MAX , der größer oder gleich 32767 ist.
  • std::numeric_limits<unsigned int>::max() entspricht UINT_MAX , der größer als oder gleich 65535 ist.
  • std::numeric_limits<long>::min() entspricht LONG_MIN , was gleich oder weniger als -2147483647 ist.
  • std::numeric_limits<long>::max() entspricht LONG_MAX , der größer oder gleich 2147483647 ist.
  • std::numeric_limits<unsigned long>::max() entspricht ULONG_MAX , der größer als oder gleich 4294967295 ist.
C ++ 11
  • std::numeric_limits<long long>::min() entspricht LLONG_MIN , was kleiner oder gleich -9223372036854775807 ist.
  • std::numeric_limits<long long>::max() entspricht LLONG_MAX , der größer oder gleich 9223372036854775807 ist.
  • std::numeric_limits<unsigned long long>::max() entspricht ULLONG_MAX , der größer oder gleich 18446744073709551615 ist.

Für Fließkommatypen T ist max() der maximale endliche Wert, während min() der niedrigste positiv normalisierte Wert ist. Weitere Member werden für Gleitkommatypen bereitgestellt, die ebenfalls implementierungsdefiniert sind, jedoch bestimmte Garantien erfüllen, die der C-Standard durch den <cfloat> -Header <cfloat> .

  • Das Mitglied digits10 gibt die Anzahl der Nachkommastellen der Präzision.
    • std::numeric_limits<float>::digits10 entspricht FLT_DIG , also mindestens 6.
    • std::numeric_limits<double>::digits10 entspricht DBL_DIG , also mindestens 10.
    • std::numeric_limits<long double>::digits10 entspricht LDBL_DIG , also mindestens 10.
  • Das min_exponent10 ist das minimale negative E, so dass 10 der Leistung E normal ist.
    • std::numeric_limits<float>::min_exponent10 entspricht FLT_MIN_10_EXP , höchstens jedoch -37.
    • std::numeric_limits<double>::min_exponent10 entspricht DBL_MIN_10_EXP , was höchstens -37 ist. std::numeric_limits<long double>::min_exponent10 entspricht LDBL_MIN_10_EXP , höchstens jedoch -37.
  • Das max_exponent10 ist das Maximum E, so dass 10 zur Potenz E endlich ist.
    • std::numeric_limits<float>::max_exponent10 entspricht FLT_MIN_10_EXP , also mindestens 37.
    • std::numeric_limits<double>::max_exponent10 entspricht DBL_MIN_10_EXP , also mindestens 37.
    • std::numeric_limits<long double>::max_exponent10 entspricht LDBL_MIN_10_EXP , also mindestens 37.
  • Wenn der Member is_iec559 den is_iec559 true hat, entspricht der Typ der Norm IEC 559 / IEEE 754, und sein Bereich wird daher durch diese Norm festgelegt.

Wertdarstellung von Gleitkommatypen

Der Standard verlangt, dass long double mindestens so viel Präzision bietet wie double , was mindestens genauso viel Präzision wie float bietet. Ein long double kann einen beliebigen Wert darstellen, den ein double kann, während ein double einen beliebigen Wert darstellen kann, den ein float kann. Die Details der Darstellung sind jedoch implementierungsdefiniert.

Bei einem Gleitkommatyp T gibt std::numeric_limits<T>::radix die von der Darstellung von T verwendete std::numeric_limits<T>::radix .

Wenn std::numeric_limits<T>::is_iec559 wahr ist, dann entspricht die Darstellung von T einem der von IEC 559 / IEEE 754 definierten Formate.

Überlauf beim Konvertieren von Ganzzahl in vorzeichenbehaftete Ganzzahl

Wenn eine vorzeichenbehaftete oder vorzeichenlose Ganzzahl in einen vorzeichenbehafteten Ganzzahlentyp konvertiert wird und ihr Wert im Zieltyp nicht darstellbar ist, wird der erzeugte Wert durch die Implementierung definiert. Beispiel:

// 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)

Basiswert (und damit Größe) einer Aufzählung

Wenn der zugrunde liegende Typ nicht explizit für einen Aufzählungstyp mit nicht angegebenem Bereich angegeben ist, wird er in einer implementierungsdefinierten Weise bestimmt.

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

Der Standard erfordert jedoch, dass der zugrunde liegende Typ einer Enumeration nicht größer als int sei denn, int und unsigned int nicht alle Werte der Enumeration darstellen. Im obigen Code könnte T also int , unsigned int oder short , aber nicht long long , um einige Beispiele zu geben.

Beachten Sie, dass eine Aufzählung dieselbe Größe (wie von sizeof ) wie ihr zugrunde liegender Typ hat.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow