Was ist die Bitgröße von long unter 64-Bit-Windows?

137

Vor longnicht allzu langer Zeit hat mir jemand gesagt, dass es auf 64-Bit-Computern keine 64-Bit-Computer gibt, die ich immer verwenden sollte int. Das ergab für mich keinen Sinn. Ich habe gesehen, dass Dokumente (wie die auf Apples offizieller Website) sagen, dass sie longbeim Kompilieren für eine 64-Bit-CPU tatsächlich 64 Bit sind. Ich habe nachgeschlagen, was es unter 64-Bit-Windows war, und festgestellt

  • Windows: longund intbleiben 32 Bit lang, und spezielle neue Datentypen werden für 64-Bit-Ganzzahlen definiert.

(von http://www.intel.com/cd/ids/developer/asmo-na/eng/197664.htm?page=2 )

Was soll ich verwenden? Soll ich so etwas wie definieren uw, sw((un) unterzeichnet Breite) als longwenn sie nicht auf Windows, und ansonsten eine Überprüfung der Ziel - CPU Bitbreite tun?

Csaba
quelle
Unter Windows mit MSVC ++ sind int und long 32-Bit: msdn.microsoft.com/en-us/library/3b2e7499.aspx . Damit z. B. Vektoren mehr als 4 G Elemente speichern können, beträgt size_t 64 Bit. Man muss also int64_t anstelle von int verwenden, um z. B. Vektoren zu iterieren, die mehr als 4G-Elemente enthalten können.
Serge Rogatch
1
In Cygwin sizeof(long) == 8sogar unter Windows :-)
Rustyx
@ SergeRogatch sollten sie verwenden size_toder einen Iteratortyp, um zu iterieren, nicht intoderint64_t
phuclv
2
@ LưuVĩnhPhúc, mit dem size_tes in der Nähe von negativen Zahlen schwierig wird, weil size_tes nicht signiert ist. Also for(size_t i=0; i<v.size()-2; i++)schlägt für Vektorgröße 0 und 1 fehl. Ein weiteres Beispiel : for(size_t i=v.size()-1; i>=0; i--).
Serge Rogatch
2
Wenn Sie mit Zeigern rechnen (dh mit size_tWerten, sollte das Ergebnis in einer Variablen vom ptrdiff_tTyp
gespeichert werden

Antworten:

260

In der Unix-Welt gab es einige mögliche Anordnungen für die Größe von Ganzzahlen und Zeigern für 64-Bit-Plattformen. Die beiden am häufigsten verwendeten waren ILP64 (eigentlich nur sehr wenige Beispiele dafür; Cray war eines davon) und LP64 (für fast alles andere). Die Akronynmen stammen von 'int, long, Zeiger sind 64-Bit' und 'long, Zeiger sind 64-Bit'.

Type           ILP64   LP64   LLP64
char              8      8       8
short            16     16      16
int              64     32      32
long             64     64      32
long long        64     64      64
pointer          64     64      64

Das ILP64 System wurde zugunsten von verlassenen LP64 (das heißt, fast all später Teilnehmer verwendet LP64, basierend auf den Empfehlungen der Aspen - Gruppe, nur Systeme mit einer langen Tradition von 64-Bit - Betrieb ein anderes Schema verwenden). Alle modernen 64-Bit-Unix-Systeme verwenden LP64. MacOS X und Linux sind moderne 64-Bit-Systeme.

Microsoft verwendet ein anderes Schema für den Übergang zu 64-Bit: LLP64 ("lang lang, Zeiger sind 64-Bit"). Dies hat den Vorteil, dass 32-Bit-Software ohne Änderung neu kompiliert werden kann. Es hat den Nachteil, dass es sich von dem unterscheidet, was alle anderen tun, und es erfordert auch, dass der Code überarbeitet wird, um 64-Bit-Kapazitäten auszunutzen. Es war immer eine Überarbeitung notwendig; Es waren nur andere Revisionen als auf Unix-Plattformen.

Wenn Sie Ihre Software anhand plattformneutraler Ganzzahltypnamen entwerfen, verwenden Sie wahrscheinlich den C99- <inttypes.h>Header, der, wenn die Typen auf der Plattform verfügbar sind, signiert (aufgelistet) und nicht signiert (nicht aufgeführt; Präfix mit 'u') enthält:

  • int8_t - 8-Bit-Ganzzahlen
  • int16_t - 16-Bit-Ganzzahlen
  • int32_t - 32-Bit-Ganzzahlen
  • int64_t - 64-Bit-Ganzzahlen
  • uintptr_t - Ganzzahlen ohne Vorzeichen, die groß genug sind, um Zeiger aufzunehmen
  • intmax_t- größte Ganzzahl auf der Plattform (möglicherweise größer als int64_t)

Sie können Ihre Anwendung dann mit diesen Typen codieren, wo es darauf ankommt, und mit Systemtypen (die möglicherweise unterschiedlich sind) sehr vorsichtig sein. Es gibt einen intptr_tTyp - einen vorzeichenbehafteten Ganzzahltyp zum Halten von Zeigern; Sie sollten planen, es nicht oder nur als Ergebnis einer Subtraktion von zwei uintptr_tWerten zu verwenden ( ptrdiff_t).

Wie die Frage zeigt (ungläubig), gibt es auf 64-Bit-Computern unterschiedliche Systeme für die Größe der ganzzahligen Datentypen. An etwas gewöhnen; Die Welt wird sich nicht ändern.

Jonathan Leffler
quelle
12
Für diejenigen, die schon lange genug dabei sind, weist der 64-Bit-Übergang einige Parallelen zum 16-Bit- bis 32-Bit-Übergang Mitte der 80er Jahre auf. Es gab Computer mit IL32 und andere mit L32 (Anpassung der neuen Notation an das alte Problem). Manchmal war 'int' 16-Bit, manchmal 32-Bit.
Jonathan Leffler
4
Vergessen Sie nicht, dass dies nur für C-ische Sprachen gilt. Andere haben vernünftigere Spezifikationen, bei denen a) der Compiler-Writer die Größe der Datentypen nicht ohne Weiteres auswählen darf oder b) die physische Darstellung der Datentypen nicht "leckt" oder c) Ganzzahlen immer unendlich groß sind.
Jörg W Mittag
2
Richtig - aber für die Sprachen, die das Verhalten angeben, gibt es überhaupt kein Problem. Zum Beispiel hat Java ein "langes", aber die Größe ist auf allen Plattformen fest (64-Bit?). Es gibt also keine Probleme beim Portieren auf einen 64-Bit-Computer. Die Größe ändert sich nicht.
Jonathan Leffler
17
@ TomFobear: ILP64 stellt ein Hauptproblem dar - wie nennt man den 32-Bit-Typ? Oder, wenn Sie den 32-Bit-Typ shortaufrufen, wie nennen Sie den 16-Bit-Typ? Und wenn Sie den 16-Bit-Typ charfür UTF-16 usw. aufrufen, wie nennen Sie den 8-Bit-Typ? Wenn Sie also LP64 verwenden, erhalten Sie 8-Bit char, 16-Bit short, 32-Bit int, 64-Bit longund Raum für eine Aufwärtserweiterung auf 128-Bit, long longwenn (falls?) Dies relevant wird. Danach haben Sie mehr Potenzen von 256 als Sie Namen in C haben (nun, ich nehme an, Sie könnten ein 256-Bit haben intmax_t, und erst dann gehen Sie aus). LP64 hat seine Vorzüge.
Jonathan Leffler
2
Vielleicht ist das für euch offensichtlich, aber ich denke, es ist erwähnenswert, dass C # andere ganzzahlige Größen als alles andere verwendet. Ich habe kürzlich die Schnittstelle zu einer DLL entdeckt, da C # 64-Bit-Longs verwendet ( msdn.microsoft.com/en-us/library/ms173105.aspx ).
Compholio
57

Es ist nicht klar, ob es sich um den Microsoft C ++ - Compiler oder die Windows-API handelt. Da es jedoch kein [c ++] - Tag gibt, gehe ich davon aus, dass es sich um die Windows-API handelt. Einige der Antworten haben unter Link Rot gelitten, daher biete ich noch einen Link an, der verrotten kann.


Weitere Informationen zu Windows - API - Typen wie INT, LONGusw. gibt es eine Seite auf MSDN:

Windows-Datentypen

Die Informationen sind auch in verschiedenen Windows-Header-Dateien wie verfügbar WinDef.h. Ich habe hier einige relevante Typen aufgelistet:

Geben Sie | ein S / U | x86 | x64
---------------------------- + ----- + -------- + ------ - -
BYTE, BOOLEAN | U | 8 Bit | 8 Bit
---------------------------- + ----- + -------- + ------ - -
KURZ | S | 16 Bit | 16 Bit
USHORT, WORT | U | 16 Bit | 16 Bit
---------------------------- + ----- + -------- + ------ - -
INT, LANG | S | 32 Bit | 32 Bit
UINT, ULONG, DWORD | U | 32 Bit | 32 Bit
---------------------------- + ----- + -------- + ------ - -
INT_PTR, LONG_PTR, LPARAM | S | 32 Bit | 64 Bit
UINT_PTR, ULONG_PTR, WPARAM | U | 32 Bit | 64 Bit
---------------------------- + ----- + -------- + ------ - -
LANG | S | 64 Bit | 64 Bit
ULONGLONG, QWORD | U | 64 Bit | 64 Bit

Die Spalte "S / U" bezeichnet vorzeichenbehaftet / vorzeichenlos.

Martin Liversage
quelle
4

Dieser Artikel über MSDN verweist auf eine Reihe von Typ-Aliasen (verfügbar unter Windows), die in Bezug auf ihre Breite etwas expliziter sind:

http://msdn.microsoft.com/en-us/library/aa505945.aspx

Obwohl Sie ULONGLONG verwenden können, um auf einen 64-Bit-Integralwert ohne Vorzeichen zu verweisen, können Sie beispielsweise auch UINT64 verwenden. (Gleiches gilt für ULONG und UINT32.) Vielleicht werden diese etwas klarer?

Ruben
quelle
1
Gibt es eine Garantie dafür, dass uint32_t und DWORD austauschbar sind? Es ist nicht schwer vorstellbar, dass dies nicht der Fall sein könnte [z. B. wenn das erstere ein 32-Bit intund das letztere ein 32-Bit ist long, würde gcc annehmen, dass ein Zeiger auf einen Typ den anderen trotz ihrer übereinstimmenden Darstellungen nicht als Alias ​​verwenden kann].
Supercat
4

Microsoft hat auch UINT_PTR und INT_PTR für Ganzzahlen definiert, die dieselbe Größe wie ein Zeiger haben.

Hier ist eine Liste von Microsoft-spezifischen Typen - sie ist Teil ihrer Treiberreferenz, aber ich glaube, sie gilt auch für die allgemeine Programmierung.

Mark Ransom
quelle
2

Der einfachste Weg, es für Ihren Compiler / Ihre Plattform kennenzulernen:

#include <iostream>

int main() {
  std::cout << sizeof(long)*8 << std::endl;
}

Die Multiplikation mit 8 besteht darin, Bits aus Bytes zu erhalten.

Wenn Sie eine bestimmte Größe benötigen, ist es häufig am einfachsten, einen der vordefinierten Typen einer Bibliothek zu verwenden. Wenn dies unerwünscht ist, können Sie das tun, was häufig mit Autoconf-Software passiert, und das Konfigurationssystem den richtigen Typ für die erforderliche Größe bestimmen lassen.

Paul de Vrieze
quelle
4
Nicht, dass es wichtig wäre, aber 8-Bit-Bytes sind nicht Teil der C-Spezifikation (Abschnitt 3.6 und 5.2.4.2.1 des C-Standards). Obwohl es schwierig ist, einen Computer zu finden, auf dem es sich nicht um 8 Bit handelt, können Sie LONG_BIT überprüfen, um festzustellen, wie groß Ihr langer Datentyp ist.
Andres
Natürlich haben Sie Recht, es ist tatsächlich architekturabhängig ("adressierbare Einheit des Datenspeichers, die groß genug ist, um ein Mitglied des Grundzeichensatzes der Ausführungsumgebung aufzunehmen"), aber die am häufigsten verwendeten Architekturen entsprechen 8 Bit.
Paul de Vrieze
Das OP fragte jedoch nicht nach seinem Compiler / seiner Plattform. Er fragte speziell nach 64-Bit-Windows - vermutlich, weil er keinen bequemen Zugriff auf ein 64-Bit-Windows-System zum Testen hat.
Quuxplusone
0

Die Größe in Bit longauf Windows-Plattformen beträgt 32 Bit (4 Byte).

Sie können dies mit überprüfen sizeof(long).

BeeOnRope
quelle
-2

Wenn Sie Ganzzahlen bestimmter Länge verwenden müssen, sollten Sie wahrscheinlich einige plattformunabhängige Header verwenden, um Ihnen zu helfen. Boost ist ein guter Ort zum Anschauen.

PolyThinker
quelle