Was ist der Unterschied zwischen einem int und einem long in C ++?

120

Korrigieren Sie mich, wenn ich falsch liege,

int ist 4 Bytes mit einem Wertebereich von -2.147.483.648 bis 2.147.483.647 (2 ^ 31)
lang ist 4 Bytes mit einem Wertebereich von -2.147.483.648 bis 2.147.483.647 (2 ^ 31)

Was ist der Unterschied in C ++? Können sie austauschbar verwendet werden?

Joel
quelle
In meinem VS2005, der auf einem 32-Bit-Prozessor ausgeführt wird, beträgt die Standardgröße von int 4 Byte.
3
Verwandte: Ist lange garantiert mindestens 32 Bit?
John Dibling
Wenn Sie portablen Code schreiben möchten, sollten Sie verwenden #include <stdint.h>und dann die Typen , die die Größe sagen. ZB uint32_t. Auf einer neuen Plattform müssen Sie nur sicherstellen, dass stdint.h für diese bestimmte Plattform richtig ist und Ihr Code wie beabsichtigt funktioniert.
BitTickler

Antworten:

112

Es ist implementierungsabhängig.

Unter Windows sind sie beispielsweise gleich, aber auf Alpha-Systemen betrug ein Long 64 Bit, während ein Int 32 Bit betrug. Dieser Artikel behandelt die Regeln für den Intel C ++ - Compiler auf variablen Plattformen. Zusammenfassen:

  OS           arch           size
Windows       IA-32        4 bytes
Windows       Intel 64     4 bytes
Windows       IA-64        4 bytes
Linux         IA-32        4 bytes
Linux         Intel 64     8 bytes
Linux         IA-64        8 bytes
Mac OS X      IA-32        4 bytes
Mac OS X      Intel 64     8 bytes  
Rob Walker
quelle
Ich denke, wir sollten erwägen, diese Antwort (eine Antwort anhand eines Beispiels) mit einigen der folgenden Details zum C ++ - Standard zu kombinieren. Der Entwurf für C ++ 0x befindet sich unter open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2798.pdf und ist markiert, damit Sie die Unterschiede zwischen ihm und der letzten Version sehen können.
Patrick Johnmeyer
Wenn Sie etwas in die relative Größenreihenfolge der Typen aufnehmen, erhalten Sie weit mehr Informationen als wenn Sie Größen für verschiedene Plattformen aufzählen - wie @ Kevin so gut sagt. (-1 Stimme)
xtofl
2
Einige Compiler verfügen sogar über Flags, mit denen Sie die Standardgröße von int und long ändern können, dh sie auf 8 oder 16 usw. erzwingen können. Weitere Informationen finden Sie in der Compiler-Dokumentation.
Martin York
7
NB , dass diese die Größen von lang
rogerdpack
1
Bitte geben Sie auch die Größen von int an.
Cegprakash
82

Die einzige Garantie, die Sie haben, sind:

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

// FROM @KTC. The C++ standard also has:
sizeof(signed char)   == 1
sizeof(unsigned char) == 1

// NOTE: These size are not specified explicitly in the standard.
//       They are implied by the minimum/maximum values that MUST be supported
//       for the type. These limits are defined in limits.h
sizeof(short)     * CHAR_BIT >= 16
sizeof(int)       * CHAR_BIT >= 16
sizeof(long)      * CHAR_BIT >= 32
sizeof(long long) * CHAR_BIT >= 64
CHAR_BIT         >= 8   // Number of bits in a byte

Siehe auch: Ist longgarantiert mindestens 32 Bit?

Martin York
quelle
1
Hmm, das gilt nicht, wenn sizeof (kurz)> = sizeof (char) wir nur die Größe von (kurz)> = 1 (nicht> = 2) kennen, die übrigens für alle Typen gilt. Nach dieser Größe von (jeder ganzzahlige Typ)> = 1. Was stimmt, zB erinnere ich mich an Größe von (int) == 1 auf dem Z80, aber gibt es keine stärkere Garantie für lange?
Andreas Magnusson
6
3.9.1.2 des C ++ - Standards geben an, dass sizeof (long)> = sizeof (int)> = sizeof (short)> = sizeof (char) 5.3.3.1 des C ++ - Standards spezifiziert, dass sizeof (char), sizeof (unsigned char) und sizeof (signiertes Zeichen) ist gleich 1. (Fortsetzung ...)
KTC
4
(... cont) Die durch die Integraltypen darstellbaren Maximal- und Minimalwerte werden in <limit.h> (und damit <climits>) als Makros definiert. Anhang E des C-Standards (1990), der durch Bezugnahme auf den C ++ - Standard aufgenommen wird, gibt die Mindestgrößen dieser Makros an. (Fortsetzung ...)
KTC
4
(... cont) und sie sind (2 ^ 15) -1, (2 ^ 15) -1, (2 ^ 31) -1 für kurz, int und lang, was sich als der Wert als herausstellt Gepostet von Martin York in seiner Antwort hier, wenn CHAR_BIT 8 ist (was auch der Mindestwert ist).
KTC
2
@ Giles: Ist das nicht das, was ich oben gesagt habe? sizeof (short) * CHAR_BITS> = 16. Plust ein paar andere Dinge. :-)
Martin York
13

Beim Kompilieren für x64 liegt der Unterschied zwischen int und long zwischen 0 und 4 Byte, je nachdem, welchen Compiler Sie verwenden.

GCC verwendet das LP64-Modell, was bedeutet, dass Ints 32-Bit sind, Longs jedoch 64-Bit im 64-Bit-Modus.

MSVC verwendet beispielsweise das LLP64-Modell, was bedeutet, dass sowohl Ints als auch Longs auch im 64-Bit-Modus 32-Bit sind.

Adrian
quelle
möglicherweise 0 Bytes? hmm
rogerdpack
12

Die C ++ - Spezifikation selbst (alte Version, aber gut genug dafür) lässt dies offen.

Es gibt vier vorzeichenbehaftete Ganzzahltypen: ' signed char', ' short int', ' int' und ' long 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.

[Fußnote: Das heißt, groß genug, um einen Wert im Bereich von INT_MIN und INT_MAX zu enthalten, wie im Header definiert <climits>. --- foonote beenden]

Kevin Haines
quelle
7

Wie Kevin Haines betont, haben Ints die natürliche Größe, die von der Ausführungsumgebung vorgeschlagen wird und die in INT_MIN und INT_MAX passen muss.

Der C89-Standard besagt, dass UINT_MAXmindestens 2 ^ 16-1, USHRT_MAX2 ^ 16-1 und ULONG_MAX2 ^ 32-1 sein sollten. Das ergibt eine Bitanzahl von mindestens 16 für kurz und int und 32 für lang. Für char heißt es ausdrücklich, dass es mindestens 8 Bits ( CHAR_BIT) haben sollte. C ++ erbt diese Regeln für die Datei limit.h, daher haben wir in C ++ dieselben grundlegenden Anforderungen für diese Werte. Sie sollten jedoch nicht daraus ableiten, dass int mindestens 2 Byte beträgt. Theoretisch könnten char, int und long alle 1 Byte sein. In diesem Fall CHAR_BITmuss es mindestens 32 sein. Denken Sie daran, dass "Byte" immer die Größe eines Zeichens hat. Wenn also char größer ist, besteht ein Byte nicht nur aus 8 Bits Mehr.

Johannes Schaub - litb
quelle
Ich dachte nicht, dass ein byteDatentyp in C ++ existiert. Das tut es nicht, oder? Wenn dies der Fall ist und a byteandere Größen als 8 Bit haben kann, ist es einfach nur dumm. Warum würden sie es ein Byte nennen, wenn es nicht unbedingt 8 Bit ist?
Alderath
6

Das hängt von Ihrem Compiler ab. Es ist garantiert, dass ein Long mindestens so groß wie ein Int ist, aber Sie können nicht garantieren, dass es länger ist.

Andru Luvisi
quelle
5

Die Anzahl der Bytes und der Wertebereich werden größtenteils von der Architektur der CPU bestimmt, nicht von C ++. C ++ legt jedoch Mindestanforderungen fest, die litb richtig erklärt hat und mit denen Martin York nur wenige Fehler gemacht hat.

Der Grund, warum Sie int und long nicht austauschbar verwenden können, ist, dass sie nicht immer gleich lang sind. C wurde auf einem PDP-11 erfunden, bei dem ein Byte 8 Bits hatte, int zwei Bytes betrug und direkt durch Hardwareanweisungen verarbeitet werden konnte. Da C-Programmierer häufig eine Vier-Byte-Arithmetik benötigten, wurde long erfunden und es waren vier Bytes, die von Bibliotheksfunktionen verarbeitet wurden. Andere Maschinen hatten andere Spezifikationen. Der C-Standard stellte einige Mindestanforderungen.

Windows-Programmierer
quelle
5

Wenn Sie sich darauf verlassen, dass der Compiler-Hersteller primitive Typgrößen implementiert, werden Sie wieder verfolgt, wenn Sie Ihren Code jemals auf einer anderen Maschinenarchitektur, einem anderen Betriebssystem oder einem anderen Compiler eines anderen Herstellers kompilieren.

Die meisten Compiler-Anbieter stellen eine Header-Datei bereit, die primitive Typen mit expliziten Typgrößen definiert. Diese primitiven Typen sollten immer dann verwendet werden, wenn Code möglicherweise auf einen anderen Compiler portiert wird (lesen Sie dies IMMER in JEDER Instanz). Zum Beispiel haben die meisten UNIX-Compiler int8_t uint8_t int16_t int32_t uint32_t. Microsoft hat INT8 UINT8 INT16 UINT16 INT32 UINT32. Ich bevorzuge Borland / CodeGear's int8 uint8 int16 uint16 int32 uint32. Diese Namen erinnern auch ein wenig an die Größe / den Bereich des beabsichtigten Werts.

Seit Jahren verwende ich Borlands explizite primitive Typnamen und #includedie folgende C / C ++ - Headerdatei (primitive.h), mit der die expliziten primitiven Typen mit diesen Namen für jeden C / C ++ - Compiler definiert werden sollen (diese Headerdatei deckt möglicherweise nicht alle ab Compiler, aber es deckt mehrere Compiler ab, die ich unter Windows, UNIX und Linux verwendet habe. Es definiert (noch) keine 64-Bit-Typen.

#ifndef primitiveH
#define primitiveH
// Header file primitive.h
// Primitive types
// For C and/or C++
// This header file is intended to define a set of primitive types
// that will always be the same number bytes on any operating operating systems
// and/or for several popular C/C++ compiler vendors.
// Currently the type definitions cover:
// Windows (16 or 32 bit)
// Linux
// UNIX (HP/US, Solaris)
// And the following compiler vendors
// Microsoft, Borland/Imprise/CodeGear, SunStudio,  HP/UX
// (maybe GNU C/C++)
// This does not currently include 64bit primitives.
#define float64 double
#define float32 float
// Some old C++ compilers didn't have bool type
// If your compiler does not have bool then add   emulate_bool
// to your command line -D option or defined macros.
#ifdef emulate_bool
#   ifdef TVISION
#     define bool int
#     define true 1
#     define false 0
#   else
#     ifdef __BCPLUSPLUS__
      //BC++ bool type not available until 5.0
#        define BI_NO_BOOL
#        include <classlib/defs.h>
#     else
#        define bool int
#        define true 1
#        define false 0
#     endif
#  endif
#endif
#ifdef __BCPLUSPLUS__
#  include <systypes.h>
#else
#  ifdef unix
#     ifdef hpux
#        include <sys/_inttypes.h>
#     endif
#     ifdef sun
#        include <sys/int_types.h>
#     endif
#     ifdef linux
#        include <idna.h>
#     endif
#     define int8 int8_t
#     define uint8 uint8_t
#     define int16 int16_t
#     define int32 int32_t
#     define uint16 uint16_t
#     define uint32 uint32_t
#  else
#     ifdef  _MSC_VER
#        include <BaseTSD.h>
#        define int8 INT8
#        define uint8 UINT8
#        define int16 INT16
#        define int32 INT32
#        define uint16 UINT16
#        define uint32 UINT32
#     else
#        ifndef OWL6
//          OWL version 6 already defines these types
#           define int8 char
#           define uint8 unsigned char
#           ifdef __WIN32_
#              define int16 short int
#              define int32 long
#              define uint16 unsigned short int
#              define uint32 unsigned long
#           else
#              define int16 int
#              define int32 long
#              define uint16 unsigned int
#              define uint32 unsigned long
#           endif
#        endif
#      endif
#  endif
#endif
typedef int8   sint8;
typedef int16  sint16;
typedef int32  sint32;
typedef uint8  nat8;
typedef uint16 nat16;
typedef uint32 nat32;
typedef const char * cASCIIz;    // constant null terminated char array
typedef char *       ASCIIz;     // null terminated char array
#endif
//primitive.h
Roger Nelson
quelle
C99-Mandate, die typdefs wie int32_t, uint64_t usw. aussehen, werden vom Compiler definiert und haben genau so viele Bits, wie der Name vermuten lässt. Bei den meisten C ++ - Compilern (einschließlich g ++) können Sie diese Konstanten in C ++ - Code verwenden.
Rmeador
5

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.

Jérôme Radix
quelle