Ich suche nach detaillierten Informationen zur Größe der grundlegenden C++ - Typen. Ich weiß, dass es von der Architektur (16 Bit, 32 Bit, 64 Bit) und dem Compiler abhängt.
Aber gibt es Standards für C++?
Ich verwende Visual Studio 2008 auf einer 32-Bit-Architektur. Folgendes bekomme ich:
char : 1 byte
short : 2 bytes
int : 4 bytes
long : 4 bytes
float : 4 bytes
double: 8 bytes
Ich habe versucht, ohne großen Erfolg zuverlässige Informationen zu finden, die die Größen von char
, short
, int
, long
, double
, float
und andere Arten von Architekten wiedergeben, die ich nicht für möglich gehalten habe.
Der C++ - Standard gibt nicht die Größe von ganzzahligen Typen in Bytes an, sondern legt Mindestbereiche fest, die diese enthalten müssen. Sie können die Mindestgröße in Bit aus dem erforderlichen Bereich ableiten. Sie können daraus die Mindestgröße in Bytes und den Wert des Makros CHAR_BIT
ableiten, das definiert die Anzahl der Bits in einem Byte (in allen, aber den dunkelsten Plattformen ist es 8, und dies ist auch möglich) ist nicht kleiner als 8).
Eine zusätzliche Einschränkung für char
besteht darin, dass seine Größe immer 1 Byte oder CHAR_BIT
Bits (daher der Name) beträgt.
Mindestbereiche laut Standard erforderlich (Seite 22) sind:
und Datentypbereiche auf MSDN :
signed char
: -127 bis 127 (Anmerkung, nicht -128 bis 127; dies berücksichtigt Plattformen mit 1-Komplement und Vorzeichen und Größe)unsigned char
: 0 bis 255char
: gleicher Bereich wie signed char
oder unsigned char
, implementierungsdefiniertsigned short
: -32767 bis 32767unsigned short
: 0 bis 65535signed int
: -32767 bis 32767unsigned int
: 0 bis 65535signed long
: -2147483647 bis 2147483647unsigned long
: 0 bis 4294967295signed long long
: -9223372036854775807 bis 9223372036854775807unsigned long long
: 0 bis 18446744073709551615Eine C++ (oder C) -Implementierung kann die Größe eines Typs in Bytes sizeof(type)
auf einen beliebigen Wert festlegen, solange
sizeof(type) * CHAR_BIT
ergibt eine Anzahl von Bits, die hoch genug sind, um die erforderlichen Bereiche zu enthaltensizeof(int) <= sizeof(long)
).Die tatsächlichen implementierungsspezifischen Bereiche finden Sie im Header <limits.h>
in C oder <climits>
in C++ (oder noch besser im Header std::numeric_limits
in <limits>
).
So finden Sie beispielsweise die maximale Reichweite für int
:
C:
#include <limits.h>
const int min_int = INT_MIN;
const int max_int = INT_MAX;
C++ :
#include <limits>
const int min_int = std::numeric_limits<int>::min();
const int max_int = std::numeric_limits<int>::max();
Für 32-Bit-Systeme lautet der De-facto-Standard ILP32 - dh int
, long
und Zeiger sind alle 32-Bit-Größen.
Für 64-Bit-Systeme ist LP64 - long
und der Zeiger 64-Bit (aber int
ist 32-Bit) der primäre Unix-Standard. Der Windows 64-Bit-Standard ist LLP64 - long long
und Pointer sind 64-Bit (aber long
und int
sind beide 32-Bit).
Einst verwendeten einige Unix-Systeme eine ILP64-Organisation.
Keine dieser De-facto-Normen ist durch die C-Norm (ISO/IEC 9899: 1999) gesetzlich vorgeschrieben, aber alle sind nach dieser Norm zulässig.
Und per Definition ist sizeof(char)
1
, ungeachtet des Tests im Perl-Konfigurationsskript.
Beachten Sie, dass es Maschinen (Crays) gab, bei denen CHAR_BIT
viel größer als 8 war. Das bedeutete, IIRC, dass sizeof(int)
auch 1 war, da sowohl char
als auch int
32 waren -bisschen.
In der Praxis gibt es so etwas nicht. Häufig können Sie erwarten, dass std::size_t
die native Ganzzahlgröße ohne Vorzeichen für die aktuelle Architektur darstellt. 16-Bit, 32-Bit oder 64-Bit, dies ist jedoch nicht immer der Fall, wie in den Kommentaren zu dieser Antwort ausgeführt.
Was alle anderen eingebauten Typen angeht, kommt es wirklich auf den Compiler an. Hier sind zwei Auszüge aus dem aktuellen Arbeitsentwurf des neuesten C++ - Standards:
Es gibt fünf standardmäßige Ganzzahltypen mit Vorzeichen: vorzeichenbehaftetes Zeichen, kurzes Int, int, langes Int und langes Long Int. In dieser Liste bietet jeder Typ mindestens so viel Speicherplatz wie in der Liste davor.
Für jeden der vorzeichenbehafteten Integer-Standardtypen gibt es einen entsprechenden (aber unterschiedlichen) vorzeichenlosen Integer-Standardtyp: vorzeichenloses Zeichen, vorzeichenloses kurzes int, vorzeichenloses int, vorzeichenloses langes int und vorzeichenloses langes int, von denen jeder dieselbe Menge belegt Lagerung und hat die gleichen Ausrichtungsanforderungen.
Wenn Sie möchten, können Sie statisch (zur Kompilierungszeit) die Größe dieser grundlegenden Typen festlegen. Es macht die Leute darauf aufmerksam, darüber nachzudenken, Ihren Code zu portieren, wenn sich die Größe der Annahmen ändert.
Es gibt Standard.
C90-Standard erfordert das
sizeof(short) <= sizeof(int) <= sizeof(long)
C99-Standard erfordert das
sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)
Hier sind die C99-Spezifikationen . Page 22 Details Größen verschiedener integraler Typen.
Hier sind die Int-Typ-Größen (Bits) für Windows-Plattformen:
Type C99 Minimum Windows 32bit
char 8 8
short 16 16
int 16 32
long 32 32
long long 64 64
Wenn Sie sich mit Portabilität befassen oder der Name des Typs die Größe widerspiegeln soll, können Sie sich den Header <inttypes.h>
ansehen, in dem die folgenden Makros verfügbar sind:
int8_t
int16_t
int32_t
int64_t
int8_t
hat garantiert eine Länge von 8 Bit und int16_t
hat garantiert eine Länge von 16 Bit usw.
Aktualisiert: C++ 11 brachte die Typen von TR1 offiziell in den Standard:
Und die "sortierten" Typen von <cstdint>
Außerdem erhalten Sie:
Diese Typen repräsentieren die kleinsten ganzzahligen Typen mit mindestens der angegebenen Anzahl von Bits. Ebenso gibt es die "schnellsten" Integer-Typen mit mindestens der angegebenen Anzahl von Bits:
Was "schnell" bedeutet, hängt von der Implementierung ab. Es muss auch nicht für alle Zwecke das schnellste sein.
Der C++ Standard sagt es so:
3.9.1, §2:
Es gibt fünf vorzeichenbehaftete Ganzzahltypen: "vorzeichenbehaftetes Zeichen", "kurzes int", "int", "langes int" und "langes langes int". In dieser Liste bietet jeder Typ mindestens so viel Speicherplatz wie in der Liste davor. Einfache Ints haben die natürliche Größe, die von der Architektur der Ausführungsumgebung vorgeschlagen wird (44). Die anderen vorzeichenbehafteten Integer-Typen werden bereitgestellt, um spezielle Anforderungen zu erfüllen.
(44) das heißt, groß genug, um jeden Wert im Bereich von INT_MIN und INT_MAX zu enthalten, wie im Header
<climits>
definiert.
Das Fazit: Es kommt darauf an, an welcher Architektur Sie arbeiten. Jede andere Annahme ist falsch.
Nein, es gibt keinen Standard für Schriftgrößen. Standard verlangt nur, dass:
sizeof(short int) <= sizeof(int) <= sizeof(long int)
Das Beste, was Sie tun können, wenn Sie Variablen mit fester Größe benötigen, ist die Verwendung von Makros wie folgt:
#ifdef SYSTEM_X
#define Word int
#else
#define Word long int
#endif
Dann können Sie Ihre Variablen mit Word definieren. Es ist nicht so, dass ich das mag, aber es ist der am tragbarsten Weg.
Wir dürfen ein Synonym für den Typ definieren, damit wir unseren eigenen "Standard" erstellen können.
Auf einer Maschine mit sizeof (int) == 4 können wir definieren:
typedef int int32;
int32 i;
int32 j;
...
Wenn wir also den Code auf eine andere Maschine übertragen, auf der eigentlich die Größe von long int 4 ist, können wir nur das einzelne Vorkommen von int neu definieren.
typedef long int int32;
int32 i;
int32 j;
...
Für Gleitkommazahlen es gibt einen Standard (IEEE754) : Floats sind 32 Bit und Double sind 64. Dies ist ein Hardwarestandard, kein C++ - Standard, daher könnten Compiler theoretisch Float und Double für andere definieren Größe, aber in der Praxis habe ich noch nie eine Architektur gesehen, die etwas anderes verwendet.
Es gibt eine Norm, die in den verschiedenen Normdokumenten (ISO, ANSI und so weiter) festgelegt ist.
Wikipedia hat eine großartige Seite, auf der die verschiedenen Typen und die maximale Anzahl gespeichert werden können: Integer in Computer Science.
Aber auch mit einem Standard-C++ - Compiler können Sie mit dem folgenden Code-Snippet relativ einfach herausfinden:
#include <iostream>
#include <limits>
int main() {
// Change the template parameter to the various different types.
std::cout << std::numeric_limits<int>::max() << std::endl;
}
Dokumentation für std :: numeric_limits finden Sie unter Roguewave . Es enthält eine Vielzahl weiterer Befehle, mit denen Sie die verschiedenen Grenzwerte ermitteln können. Dies kann mit jedem beliebigen Typ verwendet werden, der Größe übermittelt, z. B. std :: streamsize.
Johns Antwort enthält die beste Beschreibung, da diese garantiert zutreffen. Unabhängig davon, auf welcher Plattform Sie sich befinden, gibt es eine weitere gute Seite, die ausführlicher beschreibt, wie viele Bits jeder Typ enthalten MUSS: int types , die im Standard definiert sind.
Ich hoffe das hilft!
1) Tabelle N1 im Artikel " Die vergessenen Probleme der 64-Bit-Programmentwicklung "
2) Datenmodell
Sie können verwenden:
cout << "size of datatype = " << sizeof(datatype) << endl;
datatype = int
, long int
usw. Sie können die Größe für den von Ihnen eingegebenen Datentyp anzeigen.
Wenn es um eingebaute Typen für verschiedene Architekturen und verschiedene Compiler geht, führen Sie einfach den folgenden Code auf Ihrer Architektur mit Ihrem Compiler aus, um zu sehen, was er ausgibt. Unten sehen Sie meine buntu 13.04 (Raring Ringtail) 64-Bit-Ausgabe in g ++ 4.7.3. Beachten Sie auch, was unten beantwortet wurde, weshalb die Ausgabe als solche bestellt wird:
"Es gibt fünf standardmäßige Ganzzahltypen mit Vorzeichen: vorzeichenbehaftetes Zeichen, kurzes Ganzes, Ganzes Langes und Langes Langes Ganzes. In dieser Liste bietet jeder Typ mindestens so viel Speicherplatz wie die in der Liste davor stehenden."
#include <iostream>
int main ( int argc, char * argv[] )
{
std::cout<< "size of char: " << sizeof (char) << std::endl;
std::cout<< "size of short: " << sizeof (short) << std::endl;
std::cout<< "size of int: " << sizeof (int) << std::endl;
std::cout<< "size of long: " << sizeof (long) << std::endl;
std::cout<< "size of long long: " << sizeof (long long) << std::endl;
std::cout<< "size of float: " << sizeof (float) << std::endl;
std::cout<< "size of double: " << sizeof (double) << std::endl;
std::cout<< "size of pointer: " << sizeof (int *) << std::endl;
}
size of char: 1
size of short: 2
size of int: 4
size of long: 8
size of long long: 8
size of float: 4
size of double: 8
size of pointer: 8
Wie bereits erwähnt, sollte die Größe der aktuellen Architektur entsprechen. Sie könnten in limits.h
einen Höhepunkt erreichen, wenn Sie sehen möchten, wie Ihr aktueller Compiler mit den Dingen umgeht.
Wie andere geantwortet haben, lassen die "Standards" die meisten Details als "Implementierung definiert" und geben nur an, dass der Typ "char" mindestens "char_bis" breit ist und dass "char <= short <= int <= long < = long long "(float und double stimmen weitgehend mit den IEEE - Fließkommastandards überein, und long double ist in der Regel identisch mit double - kann jedoch bei aktuelleren Implementierungen größer sein).
Ein Grund dafür, dass keine sehr spezifischen und genauen Werte vorliegen, ist, dass Sprachen wie C/C++ für eine große Anzahl von Hardwareplattformen portierbar sind - einschließlich Computersystemen, bei denen die Wortgröße "char" 4 Bit betragen kann oder 7-Bit oder sogar ein anderer Wert als die "8-/16-/32-/64-Bit" -Computer, denen der durchschnittliche Heimcomputerbenutzer ausgesetzt ist. (Wortgröße bedeutet hier, wie viele Bits das System normalerweise verarbeitet. Auch hier sind es nicht immer 8 Bits, wie Benutzer von Heimcomputern erwarten.)
Wenn Sie wirklich ein Objekt (im Sinne einer Reihe von Bits, die einen ganzzahligen Wert darstellen) mit einer bestimmten Anzahl von Bits benötigen, haben die meisten Compiler eine Methode, um dies anzugeben. Aber es ist im Allgemeinen nicht portierbar, auch nicht zwischen Compilern, die von der Firma ame erstellt wurden, sondern für verschiedene Plattformen. Einige Standards und Vorgehensweisen (insbesondere limits.h und dergleichen) sind so weit verbreitet, dass die meisten Compiler die Ermittlung des am besten passenden Typs für einen bestimmten Wertebereich unterstützen, jedoch nicht die Anzahl der verwendeten Bits. (Wenn Sie also wissen, dass Sie Werte zwischen 0 und 127 speichern müssen, können Sie feststellen, dass Ihr Compiler einen 8-Bit-Typ "int8" unterstützt, der groß genug ist, um den gesamten gewünschten Bereich zu speichern, aber nicht so etwas wie einen "int7" -Typ, der für 7-Bit genau übereinstimmt.)
Hinweis: Viele Un * x-Quellpakete verwendeten das Skript "./configure", das die Fähigkeiten des Compilers/Systems überprüft und ein geeignetes Makefile und config.h ausgibt. Sie können einige dieser Skripte untersuchen, um festzustellen, wie sie funktionieren und wie sie die Fähigkeiten des Comilers/Systems testen, und ihnen folgen.
Wenn Sie an einer reinen C++ - Lösung interessiert sind, habe ich Vorlagen und nur C++ - Standardcode verwendet, um Typen zur Kompilierungszeit basierend auf ihrer Bitgröße zu definieren. Dies macht die Lösung portabel für Compiler.
Die Idee dahinter ist sehr einfach: Erstellen Sie eine Liste mit den Typen char, int, short, long, long long (signierte und nicht signierte Versionen), scannen Sie die Liste und wählen Sie mithilfe der Vorlage numeric_limits den Typ mit der angegebenen Größe aus.
Mit diesem Header erhalten Sie 8 Typen: stdtype :: int8, stdtype :: int16, stdtype :: int32, stdtype :: int64, stdtype :: uint8, stdtype :: uint16, stdtype :: uint32, stdtype :: uint64.
Wenn ein Typ nicht dargestellt werden kann, wird er zu stdtype :: null_type ausgewertet, der auch in diesem Header deklariert ist.
DER CODE UNTEN IS WIRD OHNE GARANTIE GEGEBEN, BITTE DOPPELT ÜBERPRÜFEN.
ICH BIN NEU AT AUCH METAPROGRAMMIERUNG, FÜHLEN SIE SICH FREI, DIESEN CODE ZU BEARBEITEN UND ZU KORRIGIEREN.
Getestet mit DevC++ (also eine gcc Version um 3.5)
#include <limits>
namespace stdtype
{
using namespace std;
/*
* THIS IS THE CLASS USED TO SEMANTICALLY SPECIFY A NULL TYPE.
* YOU CAN USE WHATEVER YOU WANT AND EVEN DRIVE A COMPILE ERROR IF IT IS
* DECLARED/USED.
*
* PLEASE NOTE that C++ std define sizeof of an empty class to be 1.
*/
class null_type{};
/*
* Template for creating lists of types
*
* T is type to hold
* S is the next type_list<T,S> type
*
* Example:
* Creating a list with type int and char:
* typedef type_list<int, type_list<char> > test;
* test::value //int
* test::next::value //char
*/
template <typename T, typename S> struct type_list
{
typedef T value;
typedef S next;
};
/*
* Declaration of template struct for selecting a type from the list
*/
template <typename list, int b, int ctl> struct select_type;
/*
* Find a type with specified "b" bit in list "list"
*
*
*/
template <typename list, int b> struct find_type
{
private:
//Handy name for the type at the head of the list
typedef typename list::value cur_type;
//Number of bits of the type at the head
//CHANGE THIS (compile time) exp TO USE ANOTHER TYPE LEN COMPUTING
enum {cur_type_bits = numeric_limits<cur_type>::digits};
public:
//Select the type at the head if b == cur_type_bits else
//select_type call find_type with list::next
typedef typename select_type<list, b, cur_type_bits>::type type;
};
/*
* This is the specialization for empty list, return the null_type
* OVVERRIDE this struct to ADD CUSTOM BEHAVIOR for the TYPE NOT FOUND case
* (ie search for type with 17 bits on common archs)
*/
template <int b> struct find_type<null_type, b>
{
typedef null_type type;
};
/*
* Primary template for selecting the type at the head of the list if
* it matches the requested bits (b == ctl)
*
* If b == ctl the partial specified templated is evaluated so here we have
* b != ctl. We call find_type on the next element of the list
*/
template <typename list, int b, int ctl> struct select_type
{
typedef typename find_type<typename list::next, b>::type type;
};
/*
* This partial specified templated is used to select top type of a list
* it is called by find_type with the list of value (consumed at each call)
* the bits requested (b) and the current type (top type) length in bits
*
* We specialice the b == ctl case
*/
template <typename list, int b> struct select_type<list, b, b>
{
typedef typename list::value type;
};
/*
* These are the types list, to avoid possible ambiguity (some weird archs)
* we kept signed and unsigned separated
*/
#define UNSIGNED_TYPES type_list<unsigned char, \
type_list<unsigned short, \
type_list<unsigned int, \
type_list<unsigned long, \
type_list<unsigned long long, null_type> > > > >
#define SIGNED_TYPES type_list<signed char, \
type_list<signed short, \
type_list<signed int, \
type_list<signed long, \
type_list<signed long long, null_type> > > > >
/*
* These are acutally typedef used in programs.
*
* Nomenclature is [u]intN where u if present means unsigned, N is the
* number of bits in the integer
*
* find_type is used simply by giving first a type_list then the number of
* bits to search for.
*
* NB. Each type in the type list must had specified the template
* numeric_limits as it is used to compute the type len in (binary) digit.
*/
typedef find_type<UNSIGNED_TYPES, 8>::type uint8;
typedef find_type<UNSIGNED_TYPES, 16>::type uint16;
typedef find_type<UNSIGNED_TYPES, 32>::type uint32;
typedef find_type<UNSIGNED_TYPES, 64>::type uint64;
typedef find_type<SIGNED_TYPES, 7>::type int8;
typedef find_type<SIGNED_TYPES, 15>::type int16;
typedef find_type<SIGNED_TYPES, 31>::type int32;
typedef find_type<SIGNED_TYPES, 63>::type int64;
}
Wie Sie bereits erwähnt haben, hängt dies weitgehend vom Compiler und der Plattform ab. Überprüfen Sie hierzu den ANSI-Standard http://home.att.net/~jackklein/c/inttypes.html
Hier ist der für den Microsoft-Compiler: Datentypbereiche.
Mir ist aufgefallen, dass sich alle anderen Antworten hier fast ausschließlich auf ganzzahlige Typen konzentrierten, während der Fragesteller auch nach Gleitkommazahlen fragte.
Ich glaube nicht, dass der C++ - Standard dies erfordert, aber Compiler für die gängigsten Plattformen folgen heutzutage im Allgemeinen dem IEEE754-Standard für ihre Gleitkommazahlen. Dieser Standard spezifiziert vier Arten von binären Gleitkommawerten (sowie einige BCD-Formate, die ich in C++ - Compilern noch nie unterstützt habe):
Wie ordnet man diese dann auf C++ - Typen zu? Im Allgemeinen verwendet float
eine einfache Genauigkeit. also sizeof(float) = 4
. Dann verwendet double
doppelte Genauigkeit (ich glaube, das ist die Quelle des Namens double
), und long double
kann entweder doppelte oder vierfache Genauigkeit haben (auf meinem System vierfach, aber auf 32-Bit) Systeme kann es doppelt sein). Ich kenne keine Compiler, die Gleitkommazahlen mit halber Genauigkeit anbieten.
Zusammenfassend ist dies das Übliche:
sizeof(float)
= 4sizeof(double)
= 8sizeof(long double)
= 8 oder 16Von Alex B Der C++ - Standard gibt nicht die Größe von ganzzahligen Typen in Bytes an, sondern legt Mindestbereiche fest, die sie aufnehmen können müssen. Sie können die Mindestgröße in Bit aus dem erforderlichen Bereich ableiten. Daraus können Sie die Mindestgröße in Bytes und den Wert des Makros CHAR_BIT ableiten, der die Anzahl der Bits in einem Byte definiert (in allen außer den dunkelsten Plattformen sind es 8, und es kann nicht weniger als 8 sein).
Eine zusätzliche Einschränkung für char ist, dass seine Größe immer 1 Byte oder CHAR_BIT-Bits (daher der Name) beträgt.
Die vom Standard geforderten Mindestbereiche (Seite 22) sind:
und Datentypbereiche auf MSDN:
vorzeichenbehaftetes Zeichen: -127 bis 127 (Hinweis, nicht -128 bis 127; dies unterstützt Plattformen mit 1er-Ergänzung) vorzeichenbehaftetes Zeichen: 0 bis 255 "normales" Zeichen: -127 bis 127 oder 0 bis 255 (abhängig von der Standard-Vorzeichenbehaftung) Kurz: -32767 bis 32767 ohne Vorzeichen Kurz: 0 bis 65535 mit Vorzeichen int: -32767 bis 32767 mit Vorzeichen int: 0 bis 65535 mit Vorzeichen long: -2147483647 bis 2147483647 mit Vorzeichen long: 0 bis 4294967295 mit Vorzeichen long: -9223372036854775807 bis 92233720720720720720 0 bis 18446744073709551615 Eine C++ (oder C) -Implementierung kann die Größe eines Typs in Byte sizeof (type) auf einen beliebigen Wert festlegen, solange
der Ausdruck sizeof (type) * CHAR_BIT ergibt die Anzahl der Bits, die ausreichen, um die erforderlichen Bereiche zu enthalten, und die Reihenfolge des Typs ist weiterhin gültig (z. B. sizeof (int) <= sizeof (long)). Die tatsächlichen implementierungsspezifischen Bereiche finden Sie in der Kopfzeile in C oder in C++ (oder noch besser in der Vorlage std :: numeric_limits in der Kopfzeile).
So finden Sie beispielsweise die maximale Reichweite für int:
C:
#include <limits.h>
const int min_int = INT_MIN;
const int max_int = INT_MAX;
C++:
#include <limits>
const int min_int = std::numeric_limits<int>::min();
const int max_int = std::numeric_limits<int>::max();
Dies ist richtig, aber Sie haben auch zu Recht gesagt, dass: char: 1 Byte kurz: 2 Byte int: 4 Byte lang: 4 Byte float: 4 Byte double: 8 Byte
Da 32-Bit-Architekturen immer noch die Standard- und die am häufigsten verwendeten Architekturen sind und diese Standardgrößen seit den Tagen vor 32-Bit beibehalten wurden, als der Speicher weniger verfügbar war, und aus Gründen der Abwärtskompatibilität und Standardisierung die gleichen geblieben sind. Sogar 64-Bit-Systeme neigen dazu, diese zu verwenden und Erweiterungen/Modifikationen vorzunehmen. Bitte beachten Sie dies für weitere Informationen:
unsigned char bits = sizeof(X) << 3;
wobei X
ein char
, int
, long
usw. ist. Dies gibt Ihnen die Größe von X
in Bits.