Quelle est la taille en bits de long sur Windows 64 bits?

137

Il n'y a pas si longtemps, quelqu'un m'a dit que ce longne sont pas des 64 bits sur des machines 64 bits et que je devrais toujours les utiliser int. Cela n'avait aucun sens pour moi. J'ai vu des documents (comme celui sur le site officiel d'Apple) dire qu'il longs'agit bien de 64 bits lors de la compilation pour un processeur 64 bits. J'ai cherché ce que c'était sur Windows 64 bits et j'ai trouvé

  • Windows: longet intrestent 32 bits de longueur, et de nouveaux types de données spéciaux sont définis pour les entiers 64 bits.

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

Que dois-je utiliser? Dois-je définir quelque chose comme uw, sw(largeur (non) signée) comme longsi ce n'est pas sous Windows, et sinon faire une vérification sur la taille en bits du processeur cible?

Csaba
la source
Sous Windows avec MSVC ++ int et long sont 32 bits: msdn.microsoft.com/en-us/library/3b2e7499.aspx . Cependant, pour permettre par exemple aux vecteurs de stocker plus de 4G d'éléments, size_t vaut 64 bits. Il faut donc utiliser int64_t au lieu de int pour itérer par exemple des vecteurs qui peuvent contenir plus de 4 éléments.
Serge Rogatch
1
Dans Cygwin sizeof(long) == 8, même sous Windows :-)
rustyx
@SergeRogatch ils devraient utiliser size_tou un type d'itérateur pour itérer, pas intouint64_t
phuclv
2
@ LưuVĩnhPhúc, avec size_tcela devient délicat près des nombres négatifs, car il size_tn'est pas signé. Donc for(size_t i=0; i<v.size()-2; i++)échoue pour la taille du vecteur 0 et 1. Un autre exemple: for(size_t i=v.size()-1; i>=0; i--).
Serge Rogatch
2
Si vous faites des maths sur des pointeurs (c'est-à-dire avec des size_tvaleurs, le résultat doit être conservé dans une variable de ptrdiff_ttype - qui est conçue pour être suffisamment grande pour contenir un tel résultat et est un type signé précisément pour cette raison!)
SlySven

Réponses:

261

Dans le monde Unix, il y avait quelques arrangements possibles pour les tailles d'entiers et de pointeurs pour les plates-formes 64 bits. Les deux les plus largement utilisés étaient ILP64 (en fait, seuls quelques exemples de cela; Cray en était un) et LP64 (pour presque tout le reste). Les acronynms proviennent de «int, long, les pointeurs sont 64 bits» et «longs, les pointeurs sont 64 bits».

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

Le système ILP64 a été abandonné au profit de LP64 (c'est-à-dire que presque tous les nouveaux venus ont utilisé LP64, sur la base des recommandations du groupe Aspen; seuls les systèmes avec un long héritage d'exploitation 64 bits utilisent un schéma différent). Tous les systèmes Unix 64 bits modernes utilisent LP64. MacOS X et Linux sont tous deux des systèmes 64 bits modernes.

Microsoft utilise un schéma différent pour la transition vers 64 bits: LLP64 («long long, les pointeurs sont 64 bits»). Cela a le mérite de signifier que les logiciels 32 bits peuvent être recompilés sans changement. Il a l'inconvénient d'être différent de ce que tout le monde fait et nécessite également une révision du code pour exploiter les capacités 64 bits. Il y avait toujours une révision nécessaire; c'était juste un ensemble de révisions différent de ceux nécessaires sur les plates-formes Unix.

Si vous concevez votre logiciel autour de noms de type entiers neutres de la plate-forme, probablement en utilisant l'en- <inttypes.h>tête C99 , qui, lorsque les types sont disponibles sur la plate-forme, fournit, en signé (listé) et non signé (non listé; préfixe avec 'u'):

  • int8_t - Entiers 8 bits
  • int16_t - Entiers 16 bits
  • int32_t - Entiers 32 bits
  • int64_t - Entiers 64 bits
  • uintptr_t - entiers non signés assez grands pour contenir des pointeurs
  • intmax_t- plus grande taille d'entier sur la plate-forme (peut être plus grande que int64_t)

Vous pouvez ensuite coder votre application en utilisant ces types là où cela compte, et en faisant très attention aux types de système (qui peuvent être différents). Il existe un intptr_ttype - un type entier signé pour contenir des pointeurs; vous devez prévoir de ne pas l'utiliser, ou de ne l'utiliser qu'à la suite d'une soustraction de deux uintptr_tvaleurs ( ptrdiff_t).

Mais, comme le souligne la question (incrédule), il existe différents systèmes pour les tailles des types de données entiers sur les machines 64 bits. Habituez-vous à cela; le monde ne va pas changer.

Jonathan Leffler
la source
12
Pour les utilisateurs qui existent depuis assez longtemps, la transition 64 bits présente des parallèles avec la transition 16 bits à 32 bits du milieu des années 80. Il y avait des ordinateurs qui étaient IL32 et d'autres qui étaient L32 (adaptant la nouvelle notation à l'ancien problème). Parfois, «int» était 16 bits, parfois 32 bits.
Jonathan Leffler
4
N'oubliez pas que cela ne s'applique qu'aux langages C-ish. D'autres ont des spécifications plus saines où a) le rédacteur du compilateur n'est pas autorisé à choisir la taille des types de données bon gré mal gré ou b) la représentation physique des types de données ne «fuit» pas ou c) les entiers sont toujours infiniment grands.
Jörg W Mittag
2
Vrai - mais pour les langues qui spécifient le comportement, il n'y a pas de problème en premier lieu. Par exemple, Java a un 'long', mais la taille est fixe (64 bits?), Sur toutes les plates-formes. Il n'y a donc aucun problème de portage sur une machine 64 bits; la taille ne change pas.
Jonathan Leffler
17
@TomFobear: ILP64 présente un problème majeur - comment appelez-vous le type 32 bits? Ou, si vous appelez le type 32 bits short, comment appelez-vous le type 16 bits? Et si vous appelez le type 16 bits charpour UTF-16, etc., comment appelez-vous le type 8 bits? Ainsi, l'utilisation de LP64 vous laisse avec 8 bits char, 16 bits short, 32 bits int, 64 bits long, avec de la place pour une extension vers le haut à 128 bits long longlorsque (si?) Cela devient pertinent. Après cela, vous avez plus de puissances de 256 que de noms en C (enfin, je suppose que vous pourriez avoir un 256 bits intmax_t, et alors seulement vous en manquez). Il y a du mérite à LP64.
Jonathan Leffler
2
C'est peut-être évident pour vous, mais je pense qu'il vaut la peine de noter que C # utilise des tailles d'entiers différentes de tout le reste. J'ai récemment eu une interfaçage avec une DLL car C # utilise des longs 64 bits ( msdn.microsoft.com/en-us/library/ms173105.aspx ).
Compholio
57

Il n'est pas clair si la question concerne le compilateur Microsoft C ++ ou l'API Windows. Cependant, il n'y a pas de balise [c ++] donc je suppose qu'il s'agit de l'API Windows. Certaines des réponses ont souffert de la pourriture des liens, je fournis donc un autre lien qui peut pourrir.


Pour plus d'informations sur les types d'API Windows comme INT, LONGetc., il existe une page sur MSDN:

Types de données Windows

Les informations sont également disponibles dans divers fichiers d'en-tête Windows comme WinDef.h . J'ai répertorié quelques types pertinents ici:

Type | S / U | x86 | x64
---------------------------- + ----- + -------- + ------ -
BYTE, BOOLEAN | U | 8 bits | 8 bits
---------------------------- + ----- + -------- + ------ -
SHORT | S | 16 bits | 16 bits
USHORT, WORD | U | 16 bits | 16 bits
---------------------------- + ----- + -------- + ------ -
INT, LONG | S | 32 bits | 32 bits
UINT, ULONG, DWORD | U | 32 bits | 32 bits
---------------------------- + ----- + -------- + ------ -
INT_PTR, LONG_PTR, LPARAM | S | 32 bits | 64 bits
UINT_PTR, ULONG_PTR, WPARAM | U | 32 bits | 64 bits
---------------------------- + ----- + -------- + ------ -
LONGLONG | S | 64 bits | 64 bits
ULONGLONG, QWORD | U | 64 bits | 64 bits

La colonne «S / U» indique signé / non signé.

Martin Liversage
la source
4

Cet article sur MSDN fait référence à un certain nombre d'alias de type (disponibles sous Windows) qui sont un peu plus explicites en ce qui concerne leur largeur:

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

Par exemple, bien que vous puissiez utiliser ULONGLONG pour référencer une valeur intégrale non signée 64 bits, vous pouvez également utiliser UINT64. (Il en va de même pour ULONG et UINT32.) Peut-être que ce sera un peu plus clair?

Ruben
la source
1
Y a-t-il une garantie que uint32_t et DWORD seront interchangeables? Il n'est pas difficile d'imaginer qu'ils pourraient ne pas l'être [par exemple, si le premier est un 32 bits intet le second un 32 bits long, gcc supposerait qu'un pointeur vers un type serait incapable d'aliaser l'autre malgré leurs représentations correspondantes].
supercat
4

Microsoft a également défini UINT_PTR et INT_PTR pour les entiers de la même taille qu'un pointeur.

Voici une liste de types spécifiques à Microsoft - cela fait partie de leur référence de pilote, mais je pense que c'est également valable pour la programmation générale.

Mark Ransom
la source
2

Le moyen le plus simple de le connaître pour votre compilateur / plateforme:

#include <iostream>

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

La multiplication par 8 consiste à obtenir des bits à partir d'octets.

Lorsque vous avez besoin d'une taille particulière, il est souvent plus simple d'utiliser l'un des types prédéfinis d'une bibliothèque. Si cela n'est pas souhaitable, vous pouvez faire ce qui se passe souvent avec le logiciel autoconf et demander au système de configuration de déterminer le bon type pour la taille requise.

Paul de Vrieze
la source
4
Ce n'est pas que cela compte, mais les octets de 8 bits ne font pas réellement partie de la spécification C (clauses 3.6 et 5.2.4.2.1 de la norme C). Bien que vous ayez du mal à trouver une machine où ce n'est pas 8 bits, vous pouvez vérifier LONG_BIT pour voir la taille de votre long type de données.
Andres
Bien sûr, vous avez raison, elle dépend en fait de l'architecture ("unité adressable de stockage de données suffisamment grande pour contenir n'importe quel membre du jeu de caractères de base de l'environnement d'exécution"), mais les architectures les plus couramment utilisées sont égales à 8 bits.
Paul de Vrieze
Mais l'OP n'a pas posé de questions sur son compilateur / plate-forme; il a posé une question spécifique sur Windows 64 bits - probablement parce qu'il n'a pas d'accès pratique à un système Windows 64 bits pour tester.
Quuxplusone
0

La taille en bits de longsur les plates-formes Windows est de 32 bits (4 octets).

Vous pouvez vérifier cela en utilisant sizeof(long).

BeeOnRope
la source
-2

Si vous avez besoin d'utiliser des entiers d'une certaine longueur, vous devriez probablement utiliser des en-têtes indépendants de la plate-forme pour vous aider. Boost est un bon endroit à regarder.

PolyThinker
la source