Wie lautet der C ++ - Standard für die Größe des Typs int, long?


696

Ich suche nach detaillierten Informationen bezüglich der Größe grundlegender 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 zu finden, ohne viel Erfolg, zuverlässige Informationen unter Angabe der Größen char, short, int, long, double, float(und andere Arten ich nicht gedacht) unter verschiedenen Architekturen und Compiler.


18
@thyrgle ist nicht freiwillig ... es gibt so viele Architekturen zu unterstützen, dass es flexibel sein muss.
Krakkos


4
Warum entfernen sie nicht alle vagen Typen und standardisieren alles auf bestimmte Bitlängentypen, z. B. int32_t, uint32_t, int64_t usw.
Developerbmw

5
@thyrgle Es ist eigentlich ziemlich schwierig, so etwas zu standardisieren. Im Gegensatz zu Java, wo diese Dinge aufgrund der Funktionsweise der JVM konstant sind, muss sich C / C ++ im Wesentlichen an das System halten, auf dem sie ausgeführt werden, ohne ausgefallene Abstraktionsschichten (zumindest nicht so viele wie bei Java). zwischen. Wenn die Größe des int so wichtig ist, kann man verwenden int16_t, int32_tund int64_t(brauche das iostreamInclude dafür, wenn ich mich richtig erinnere). Das Schöne daran ist, dass int64_t auf einem 32-Bit-System keine Probleme haben sollte (dies wirkt sich jedoch auf die Leistung aus).
Rbaleksandar

5
@rbaleksandar Sie sind tatsächlich in definiert <cstdint>, nicht <iostream>.
Justin Time - Stellen Sie Monica

Antworten:


685

Der C ++ - Standard gibt nicht die Größe von Integraltypen in Bytes an, sondern Mindestbereiche, die sie halten 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 CHAR_BITMakros ableiten , das die Anzahl der Bits in einem Byte definiert . Auf allen außer den dunkelsten Plattformen ist es 8, und es kann nicht weniger als 8 sein. Das liegt daran, dass es groß genug sein muss, um "die 8-Bit-Codeeinheiten der Unicode UTF-8-Codierungsform" aufzunehmen.

Eine zusätzliche Einschränkung charbesteht darin, dass seine Größe immer 1 Byte oder CHAR_BITBits beträgt (daher der Name). Dies ist in der Norm ausdrücklich angegeben.

Der C-Standard ist eine normative Referenz für den C ++ - Standard. Obwohl diese Anforderungen nicht explizit angegeben werden, erfordert C ++ die vom C-Standard geforderten Mindestbereiche (Seite 22), die mit denen ab Datentypbereichen identisch sind MSDN :

  1. signed char: -127 bis 127 (Anmerkung, nicht -128 bis 127; dies ermöglicht Plattformen mit 1er-Komplement und Vorzeichen und Größe)
  2. unsigned char: 0 bis 255
  3. "plain" char: gleicher Bereich wie signed charoder unsigned char, implementierungsdefiniert
  4. signed short: -32767 bis 32767
  5. unsigned short: 0 bis 65535
  6. signed int: -32767 bis 32767
  7. unsigned int: 0 bis 65535
  8. signed long: -2147483647 bis 2147483647
  9. unsigned long: 0 bis 4294967295
  10. signed long long: -9223372036854775807 bis 9223372036854775807
  11. unsigned long long: 0 bis 18446744073709551615

Eine C ++ (oder C) -Implementierung kann die Größe eines Typs in Bytes sizeof(type)für einen beliebigen Wert definieren, solange

  1. Der Ausdruck wird sizeof(type) * CHAR_BITmit einer Anzahl von Bits ausgewertet, die hoch genug sind, um die erforderlichen Bereiche zu enthalten
  2. Die Reihenfolge des Typs ist weiterhin gültig (z sizeof(int) <= sizeof(long). B. ).

Wenn wir das alles zusammenfassen, ist uns garantiert, dass:

  • char,, signed charund unsigned charsind mindestens 8 Bits
  • signed short, unsigned short, signed int, Und unsigned intsind mindestens 16 Bits
  • signed longund unsigned longsind mindestens 32 Bit
  • signed long longund unsigned long longsind mindestens 64 Bit

Es wird keine Garantie für die Größe von floatoder übernommen, doubleaußer dass dies doublemindestens so viel Präzision bietet wie float.

Die tatsächlichen implementierungsspezifischen Bereiche finden Sie im <limits.h>Header in C oder <climits>in C ++ (oder noch besser std::numeric_limitsim <limits>Header).

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();

49
Vielmehr verwendet der C ++ - Standard das Wort Byte , um "1 char" zu bedeuten , und nicht die übliche Bedeutung.
Ben Voigt

4
@Programmer Lesen Sie die Antwort (Punkt 1 in Klammern) oder den Wortlaut des tatsächlichen Standards (in der Antwort verlinkt). Der C-Standard unterstützt die Komplementarchitekturen von 1, die sich von den am weitesten verbreiteten Komplementarchitekturen von 2 unterscheiden. Die garantierten Mindestbereiche unterscheiden sich fast immer von den tatsächlichen Bereichen, die eine Implementierung bereitstellt.
Alex B

9
@Alex B Sie haben in Ihrer Antwort nichts über Double erwähnt. Können Sie bitte Ihre Antwort für Gleitkommavariablen aktualisieren?
Cool_Coder

3
@Cool_Coder: Fließkomma ist ein ganz zusätzlicher Fischkessel, der die Größe der Pfosten leicht verdoppelt.
Deduplikator

3
@Mooing Duck: "Alle Versionen von C ++ erforderten 256 unterschiedliche Werte [für signierte Zeichentypen]" Nein, das stimmte erst, als es in den neueren C ++ - Spezifikationen behoben wurde. Die älteren Spezifikationen erlaubten signierten Zeichentypen, Bitmuster zu haben, die keiner Zahl zugeordnet sind, sodass ihnen die Anforderung fehlte, dass 256 verschiedene Werte vorhanden sein müssen. "Bei vorzeichenlosen Zeichentypen stellen alle möglichen Bitmuster der Wertdarstellung Zahlen dar. Diese Anforderungen gelten nicht für andere Typen."
Adrian McCarthy

241

Für 32-Bit-Systeme ist der De-facto-Standard ILP32 - das heißt int, longund Zeiger sind alle 32-Bit-Größen.

Bei 64-Bit-Systemen ist der primäre Unix-De-facto-Standard LP64 - longund der Zeiger ist 64-Bit (aber int32-Bit). Die Windows 64-Bit - Standard ist LLP64 - long longund Zeiger sind 64-Bit (aber longund intsind jeweils 32-bit).

Zu einer Zeit verwendeten einige Unix-Systeme eine ILP64-Organisation.

Keine dieser De-facto-Normen ist in der C-Norm (ISO / IEC 9899: 1999) gesetzlich geregelt, aber alle sind von dieser zugelassen.

Und per Definition sizeof(char)ist dies 1ungeachtet des Tests im Perl-Konfigurationsskript der Fall.

Beachten Sie, dass es Maschinen (Crays) CHAR_BITgab, die viel größer als 8 waren. Das bedeutete, IIRC, das sizeof(int)war auch 1, weil beide charund int32-Bit waren.


73
+1 für die Angabe, wie die Dinge tatsächlich in den Fällen sind, die für die meisten von Bedeutung sind, und nicht wie die Dinge theoretisch sind. Wenn Sie 32bit wollen, verwenden Sie int, wenn Sie 64bit wollen, verwenden Sie long long. Wenn Sie native möchten, verwenden Sie size_t. Vermeiden Sie "normal" lange, da es variiert. Das sollte für die meisten Anwendungen funktionieren.
Eloff

37
+1 für die Antwort. @Eloff: im Gegenteil ... wenn Sie eine 32-Bit-Verwendung [u]int32_toder ähnliches wünschen, wenn Sie eine 64-Bit-Verwendung wünschen [u]int64_t... wenn Sie keinen Header für sie haben, laden Sie einen herunter oder erstellen Sie einen, vorzugsweise mit einer Auswahl der Kompilierungszeit von solche Typen oder statische Zusicherungen zur Überprüfung der Größe. pubs.opengroup.org/onlinepubs/009695299/basedefs/stdint.h.html Wenn die genauen Größen nicht so wichtig sind und Sie sich nur darum kümmern, dass sie mindestens so groß sind, gilt Ihr Rat für gängige moderne PC / Server-Plattformen.
Tony Delroy

8
Beachten Sie, dass nicht nur alte Cray-Maschinen CHAR_BIT> 8 haben. ZB DSPs haben häufig CHAR_BIT von 16 oder 32. (siehe z. B. diese )
Nr.

2
@nos: Danke für den Link. Es ist sehr hilfreich, moderne, aktuelle Systeme für die Oddball-Fälle identifizieren zu lassen. Was ist aus Neugier der Code, der auf diesen Maschinen eingestellt ist? Wenn der Codesatz UTF-16 ist, ist 0xFFFF kein gültiges Zeichen, und wenn der Codesatz ein ISO 8859-x-Codesatz ist, ist 0xFFFF wiederum kein gültiges Zeichen (Zeichencodes von 0x00 bis 0xFF sind gültig). Ich bin noch nicht davon überzeugt, dass es ein Problem beim Erkennen von EOF gibt, aber es gibt sicherlich Raum für Vorsicht und wahrscheinlich für das Schreiben und Verwenden einer Funktion, int get_char(FILE *fp, char *c)die EOF oder 0 zurückgibt und setzt *c.
Jonathan Leffler

2
@joelw: C11 erfordert, dass uint32_t x=1,y=2;der Wert von x-y4294967295 auf Plattformen sein muss, auf denen "int" 32 Bit oder kleiner ist, und -1 auf Plattformen, auf denen "int" 33 Bit oder mehr beträgt. Ferner erfordert es, dass x*yeine modulare Arithmetik für alle Werte von x und y ausgewertet werden muss, wenn "int" 32 Bit oder kleiner ist, und eine konventionelle Arithmetik, wenn 65 Bit oder mehr, aber keine Anforderungen an das, was mit großen Werten passieren kann von x und y, wenn "int" 33 bis 64 Bit beträgt.
Supercat

88

In der Praxis gibt es so etwas nicht. Oft können Sie erwarten std::size_t, dass die vorzeichenlose native Ganzzahlgröße in der aktuellen Architektur dargestellt wird. dh 16-Bit, 32-Bit oder 64-Bit, aber dies ist nicht immer der Fall, wie in den Kommentaren zu dieser Antwort ausgeführt.

Was alle anderen integrierten Typen betrifft, hängt dies wirklich vom Compiler ab. Hier sind zwei Auszüge aus dem aktuellen Arbeitsentwurf des neuesten C ++ - Standards:

Es gibt fünf standardmäßige vorzeichenbehaftete Ganzzahltypen: signiertes Zeichen, kurzes int, int, langes int und langes langes int. In dieser Liste bietet jeder Typ mindestens so viel Speicherplatz wie die vorhergehenden in der Liste.

Für jeden der vorzeichenbehafteten Standard-Integer-Typen gibt es einen entsprechenden (aber unterschiedlichen) Standard-Integer-Typ ohne Vorzeichen: vorzeichenloses Zeichen, vorzeichenloses kurzes int, vorzeichenloses int, vorzeichenloses long int und vorzeichenloses long long int, von denen jeder die gleiche Menge von belegt Lagerung und hat die gleichen Ausrichtungsanforderungen.

Wenn Sie möchten, können Sie die Größe dieser grundlegenden Typen statisch (zur Kompilierungszeit) festlegen. Es macht die Leute darauf aufmerksam, über die Portierung Ihres Codes nachzudenken, wenn sich die Größe der Annahmen ändert.


7
Guter Post. Eine andere Sache, die erforderlich ist, sind die folgenden kleinsten Bitgrößen (dokumentiert in c89 / c99 zusammen mit limits.h und übernommen von c ++): char> = 8, short und int> = 16, long> = 32.
Johannes Schaub - litb

1
Auf einer 8-Bit-AVR-Plattform beträgt size_t nicht 8 Bit, sondern 16 Bit, da die Zeiger- und Int-Größen 16 Bit betragen. Die native Datengröße des Prozessors hängt also nicht mit size_t zusammen.
Robotbugs

80

Es gibt Standard.

Der C90-Standard erfordert dies

sizeof(short) <= sizeof(int) <= sizeof(long)

Der C99-Standard erfordert dies

sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)

Hier sind die C99-Spezifikationen . Page 22 Detailgrößen verschiedener integraler Typen.

Hier sind die int-Typgröß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 möchten, dass der Name des Typs die Größe widerspiegelt, können Sie sich die Kopfzeile ansehen <inttypes.h>, in der die folgenden Makros verfügbar sind:

int8_t
int16_t
int32_t
int64_t

int8_tist garantiert 8 Bit und int16_tgarantiert 16 Bit usw.


8
Minor nitpick: Wo steht der Standard sizeof(long) < sizeof(long long)im Gegensatz zum symmetrischen sizeof(long) <= sizeof(long long)?
Jonathan Leffler

2
@ JonathonLeffler - siehe C99 5.2.4.2.1 - Größen von Ganzzahltypen. minsizeof (int) == 16 Bit, minsizeof (long) == 32 Bit, minsizeof (long long) == 64 Bit. Ich denke, Sie haben Recht mit dem <=, da keine maxsizeof (Typ) angegeben ist.
Jesse Chisholm

Ähnlich sizeof (float) <= sizeof (double) <= sizeof (long double). Gemäß C99 7.12 Absatz 2.
Jesse Chisholm

38

Wenn Sie Typen mit fester Größe benötigen, verwenden Sie Typen wie uint32_t (vorzeichenlose Ganzzahl 32 Bit), die in stdint.h definiert sind . Sie sind in C99 angegeben .


10
Sie sind angegeben, aber nicht erforderlich.
Dreamlax

2
@dreamlax Welche Plattformen enthalten es nicht?
Levi Morrison

3
@ LeviMorrison: Jede Plattform, die sie nicht in der erforderlichen Form hat. Eine Plattform, die CHAR_BIT == 16zum Beispiel nicht hat int8_t. Jede Plattform, die kein Zweierkomplement verwendet, hat keine davon (da das Zweierkomplement vom Standard verlangt wird).
DevSolar

36

Aktualisiert: C ++ 11 brachte die Typen von TR1 offiziell in den Standard:

  • lang lang int
  • unsigned long long int

Und die "Größe" Typen aus <cstdint>

  • int8_t
  • int16_t
  • int32_t
  • int64_t
  • (und die nicht signierten Gegenstücke).

Plus bekommen Sie:

  • int_least8_t
  • int_least16_t
  • int_least32_t
  • int_least64_t
  • Plus die nicht signierten Gegenstücke.

Diese Typen stellen die kleinsten Ganzzahltypen mit mindestens der angegebenen Anzahl von Bits dar. Ebenso gibt es die "schnellsten" Ganzzahltypen mit mindestens der angegebenen Anzahl von Bits:

  • int_fast8_t
  • int_fast16_t
  • int_fast32_t
  • int_fast64_t
  • Plus die nicht signierten Versionen.

Was "schnell" bedeutet, hängt von der Implementierung ab. Es muss auch nicht für alle Zwecke das schnellste sein.


Dies ist jetzt Teil des C ++ 11-Standards.
Jaan

2
"schnell" bedeutet nur auf die Hardwarearchitektur zugeschnitten. Wenn die Register 16-Bit sind, ist int_fast8_t ein 16-Bit-Wert. Wenn die Register 32-Bit sind, sind int_fast8_t und int_fast16_t beide 32-Bit-Werte. usw. Siehe C99 Abschnitt 7.18.1.3 Absatz 2.
Jesse Chisholm

19

Der C ++ Standard sagt es so:

3.9.1, §2:

Es gibt fünf vorzeichenbehaftete Ganzzahltypen: "signiertes Zeichen", "kurzes int", "int", "langes int" und "langes langes int". In dieser Liste bietet jeder Typ mindestens so viel Speicherplatz wie die vorhergehenden in der Liste. Einfache Ints haben die natürliche Größe, die von der Architektur der Ausführungsumgebung vorgeschlagen wird (44). Die anderen vorzeichenbehafteten Ganzzahltypen werden bereitgestellt, um spezielle Anforderungen zu erfüllen.

(44) das heißt, groß genug, um einen Wert im Bereich von INT_MIN und INT_MAX zu enthalten, wie im Header definiert <climits> .

Das Fazit: Es kommt darauf an, an welcher Architektur Sie arbeiten. Jede andere Annahme ist falsch.


12

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 fester Größe möchten, ist die Verwendung von Makros wie folgt:

#ifdef SYSTEM_X
  #define WORD int
#else
  #define WORD long int
#endif

Dann können Sie WORD verwenden, um Ihre Variablen zu definieren. Es ist nicht so, dass ich das mag, aber es ist der tragbarste Weg.


4
Das Problem ist, dass WORD im Programm in Bereiche verteilt wird, die nicht wirklich von einer festen Größe abhängig sind (siehe Windows-Code). Wie ich beim Wechsel von einem 16-Bit- zu einem 32-Bit-System herausgefunden habe, haben Sie das gleiche Problem, das WORD lösen sollte.
Lilburne

@liburne Natürlich sollten Sie WORD nur verwenden, wenn Sie eine Variable mit fester Größe benötigen, z. B. wenn Sie aus einer Datei lesen / schreiben. Wenn ein Code nicht wirklich von einer festen Größe abhängig ist, sollten Sie normale "int" -Variablen verwenden.
Emiliano

3
Das Beste, was Sie tun können, um tragbare Größen zu erhalten, sollte sein#include <boost/cstdint.hpp>
kizzx2

11

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 die Größe von long int tatsächlich 4 beträgt, können wir nur das einzelne Vorkommen von int neu definieren.

typedef long int int32;

int32 i;
int32 j;
...

1
Dies ist angesichts des Standard-Headers <stdint.h>(C99 und höher und je nachdem, welcher C ++ - Standard die C99-Version der C-Bibliothek übernommen hat) nicht erforderlich .
Keith Thompson

8

Für Gleitkommazahlen gibt es einen Standard (IEEE754) : Floats sind 32 Bit und Doubles sind 64. Dies ist ein Hardwarestandard, kein C ++ - Standard, daher könnten Compiler theoretisch Float und Double auf eine andere Größe definieren, aber in der Praxis I ' Ich habe noch nie eine Architektur gesehen, die etwas anderes verwendet.


2
Die Einhaltung von IEEE 754 (auch bekannt als IEC 559) ist in C ++ jedoch optional (wahrscheinlich auch C, aber ich bin nicht sicher). Siehe std :: numeric_limits :: is_iec559.
Drew Hall

1
Dann haben Sie den Compiler von TI für TMS320C28xx-DSPs nicht gesehen, doubleder die gleiche Größe wie float(und intdie gleiche Größe char, beide sind 16 Bit) hat. Aber sie haben ein 64-Bit long double.
Starblue

7

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 das Maximum, das sie speichern können, erklärt werden: Ganzzahl in der Informatik.

Selbst mit einem Standard-C ++ - Compiler können Sie dies mithilfe des folgenden Codeausschnitts 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;
}

Die Dokumentation zu std :: numeric_limits finden Sie bei Roguewave . Es enthält eine Vielzahl weiterer Befehle, die Sie aufrufen können, um die verschiedenen Grenzwerte herauszufinden. 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 gilt. Unabhängig davon, auf welcher Plattform Sie sich befinden, gibt es eine weitere gute Seite, auf der detaillierter beschrieben wird, wie viele Bits jeder Typ enthalten MUSS: int-Typen , die im Standard definiert sind.

Ich hoffe das hilft!



7

Sie können verwenden:

cout << "size of datatype = " << sizeof(datatype) << endl;

datatype = int, long intUsw. Sie können die Größe sehen , je nachdem , welchen Datentyp angezeigt werden .


7

Wenn es um integrierte 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 zeigt meine 64-Bit-Ausgabe von Ubuntu 13.04 (Raring Ringtail) g ++ 4.7.3. Bitte beachten Sie auch, was unten beantwortet wurde, weshalb die Ausgabe als solche bestellt wird:

"Es gibt fünf standardmäßige vorzeichenbehaftete Ganzzahltypen: vorzeichenbehaftetes Zeichen, kurzes int, int, langes int und langes langes int. In dieser Liste bietet jeder Typ mindestens so viel Speicherplatz wie die vorhergehenden in der Liste."

#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

sizeof(char)sollte nicht enthalten sein.
Ven

3

Wie bereits erwähnt, sollte die Größe die aktuelle Architektur widerspiegeln. Sie könnten einen limits.hBlick darauf werfen, wenn Sie sehen möchten, wie Ihr aktueller Compiler mit Dingen umgeht.


Danke, aber ich würde gerne wissen, welche Größen für Architekturen ich nicht selbst habe (wie 64 Bit). Dieses Tutorial spricht nur über 32-Bit-Architekturen ...
Jérôme

2

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-Gleitkommastandards überein, und long double ist normalerweise dasselbe wie double - kann jedoch bei aktuelleren Implementierungen größer sein).

Ein Grund dafür, dass keine sehr spezifischen und genauen Werte vorliegen, liegt darin, dass Sprachen wie C / C ++ für eine große Anzahl von Hardwareplattformen portabel sind - einschließlich Computersystemen, bei denen die Wortgröße "char" 4 Bit betragen kann oder 7-Bit oder sogar einen anderen Wert als die "8- / 16- / 32- / 64-Bit" -Computer, denen der durchschnittliche Benutzer eines Heimcomputers ausgesetzt ist. (Die Wortgröße bedeutet hier, wie viele Bit breit das System normalerweise ist. Auch hier sind es nicht immer 8 Bit, wie es Benutzer von Heimcomputern erwarten.)

Wenn Sie wirklich ein Objekt (im Sinne einer Reihe von Bits, die einen ganzzahligen Wert darstellen) einer bestimmten Anzahl von Bits benötigen, haben die meisten Compiler eine Methode, um dies anzugeben. Aber es ist im Allgemeinen nicht portierbar, selbst zwischen Compilern der Firma ame, sondern für verschiedene Plattformen. Einige Standards und Praktiken (insbesondere limit.h und dergleichen) sind häufig genug, dass die meisten Compiler die Ermittlung des am besten geeigneten Typs für einen bestimmten Wertebereich unterstützen, jedoch nicht die Anzahl der verwendeten Bits. (Das heißt, wenn Sie wissen, dass Sie Werte zwischen 0 und 127 halten müssen, können Sie feststellen, dass Ihr Compiler einen 8-Bit-Typ vom Typ "int8" unterstützt, der groß genug ist, um den gesamten gewünschten Bereich zu halten, aber nicht so etwas wie ein Typ "int7", der für 7-Bit genau übereinstimmt.)

Hinweis: Viele Un * x-Quellpakete verwendeten das Skript "./configure", mit dem die Funktionen des Compilers / Systems überprüft und ein geeignetes Makefile und config.h ausgegeben werden. Sie können einige dieser Skripte untersuchen, um festzustellen, wie sie funktionieren und wie sie die Comiler- / Systemfunktionen prüfen, und ihren Anweisungen folgen.


1

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. Dadurch ist die Lösung für alle Compiler portabel.

Die Idee dahinter ist sehr einfach: Erstellen Sie eine Liste mit den Typen char, int, short, long, long long (Versionen mit und ohne Vorzeichen) und scannen Sie die Liste. Wählen Sie mithilfe der Vorlage numeric_limits den Typ mit der angegebenen Größe aus.

Einschließlich dieses Headers haben Sie 8 Typ 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 als stdtype :: null_type ausgewertet, der ebenfalls in diesem Header deklariert ist.

DER CODE UNTEN WIRD OHNE GARANTIE GEGEBEN, BITTE DOPPELT ÜBERPRÜFEN.
Ich bin NEU BEI 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;

}

0
unsigned char bits = sizeof(X) << 3;

wo Xist ein char, int, longetc .. wird Ihnen Größe Xin Bits.


1
Ein Zeichen besteht nicht immer aus 8 Bit, daher funktioniert Ihr Ausdruck nicht auf Architekturen mit Nicht-8-Bit-Zeichen . Nur sizeof(type)*CHAR_BIThält
phuclv

Selbst wenn CHAR_BITgarantiert 8 Bit wären, << 3ist dies nur eine verschleierte Art zu schreiben * 8oder * CHAR_BIT.
Keith Thompson

0

Von Alex B Der C ++ - Standard gibt nicht die Größe von Integraltypen in Bytes an, sondern Mindestbereiche, die sie halten 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 CHAR_BIT-Makros ableiten, das die Anzahl der Bits in einem Byte definiert (auf allen Plattformen außer den dunkelsten Plattformen sind es 8, und es kann nicht weniger als 8 sein).

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.

Die vom Standard geforderten Mindestbereiche (Seite 22) sind:

und Datentypbereiche auf MSDN:

signiertes Zeichen: -127 bis 127 (Hinweis, nicht -128 bis 127; dies bietet Platz für 1-Komplement-Plattformen) vorzeichenloses Zeichen: 0 bis 255 "einfaches" Zeichen: -127 bis 127 oder 0 bis 255 (abhängig von der Standard-Zeichen-Signatur) signiert kurz: -32767 bis 32767 unsigned short: 0 bis 65535 signiert int: -32767 bis 32767 unsigned int: 0 bis 65535 signiert long: -2147483647 bis 2147483647 unsigned long: 0 bis 4294967295 signiert long long: -9223372036854775807 bis 9223372036854775807 0 bis 18446744073709551615 Eine C ++ (oder C) -Implementierung kann die Größe eines Typs in Byte Größe von (Typ) für einen beliebigen Wert definieren, 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 im Header in C oder in C ++ (oder noch besser in std :: numeric_limits im Header).

So finden Sie beispielsweise den maximalen Bereich 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: 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 Standardarchitektur sind und am häufigsten verwendet werden und diese Standardgrößen seit den Tagen vor 32 Bit beibehalten wurden, als weniger Speicher verfügbar war, und aus Gründen der Abwärtskompatibilität und Standardisierung gleich geblieben sind. Sogar 64-Bit-Systeme neigen dazu, diese zu verwenden und haben Erweiterungen / Modifikationen. Bitte beachten Sie dies für weitere Informationen:

http://en.cppreference.com/w/cpp/language/types


0

Ich stelle fest, dass sich alle anderen Antworten hier fast ausschließlich auf integrale Typen konzentriert haben, 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 Gleitkommazahlen (sowie einige BCD-Formate, für die ich in C ++ - Compilern noch nie Unterstützung gesehen habe):

  • Halbe Genauigkeit (binär16) - 11-Bit-Signifikand, Exponentenbereich -14 bis 15
  • Einfache Genauigkeit (binär32) - 24-Bit-Signifikand, Exponentenbereich -126 bis 127
  • Doppelte Genauigkeit (binär64) - 53-Bit-Signifikand, Exponentenbereich -1022 bis 1023
  • Vierfachgenauigkeit (binär128) - 113-Bit-Signifikand, Exponentenbereich -16382 bis 16383

Wie ordnet sich das dann C ++ - Typen zu? Im Allgemeinen floatverwendet die einfache Genauigkeit; also , sizeof(float) = 4. Dann doubleverwendet doppelte Genauigkeit (ich glaube , das ist die Quelle des Namen double) und long doublekann entweder doppelte oder vierfache Präzision sein (es ist vervierfachen auf meinem System, aber auf 32-Bit - Systemen kann es doppelt so hoch sein). Ich kenne keine Compiler, die Gleitkommazahlen mit halber Genauigkeit bieten.

Zusammenfassend ist dies das Übliche:

  • sizeof(float) = 4
  • sizeof(double) = 8
  • sizeof(long double) = 8 oder 16

Komisch, dass ich zu dieser Frage gekommen bin, um mich zu fragen, warum Jeff mehr Bytes verwendet, als er braucht.
Aniruddha Varma


-2

Sie können Variablen verwenden, die von Bibliotheken wie OpenGL , Qt usw. bereitgestellt werden .

Zum Beispiel Qt bietet qint8 (garantiert 8-Bit auf allen von Qt unterstützten Plattformen sein), qint16, qint32, qint64, quint8, quint16, quint32, quint64 usw.


1
Beantwortet die Frage nicht
EvilTeach

-8

Auf einem 64-Bit-Computer:

int: 4
long: 8
long long: 8
void*: 8
size_t: 8

2
Auf einigen 64-Bit-Computern sind intes 8 Bytes, die andere ist jedoch nicht garantiert. Es gibt nichts, was besagt, dass chares nur 8 Bit sein sollte. Es darf haben sizeof(void*)==4, obwohl es 64 Bit ist.
Skyking

-10

Es gibt vier Arten von Ganzzahlen, die auf der Größe basieren:

  • kurze Ganzzahl: 2 Byte
  • lange Ganzzahl: 4 Byte
  • lange lange ganze Zahl: 8 Byte
  • Ganzzahl: hängt vom Compiler ab (16 Bit, 32 Bit oder 64 Bit)

11
Falsch, sie hängen alle von der Architektur ab, wobei die Mindestbereiche in einer der anderen Antworten beschrieben sind. Nichts hält eine Implementierung zu haben short, intund longalle 32 - Bit - Integer.
Matteo Italia

Sie haben nicht einmal die richtigen Namen für die Typen verwendet. Die Namen verwenden das Schlüsselwort int, nicht das Wort "Ganzzahl".
Keith Thompson
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.