Il n'y a pas si longtemps, quelqu'un m'a dit que long
ne sont pas 64 bits sur des machines 64 bits et que je devrais toujours utiliser int
. Cela n'a pas de sens pour moi. J'ai vu des documents (comme celui du site officiel d'Apple) dire que long
sont bien 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:
long
etint
conservent une longueur de 32 bits et de nouveaux types de données spéciaux sont définis pour les entiers 64 bits.
(de http://www.intel.com/cd/ids/developer/asmo-na/eng/197664.htm?page=2 )
Que devrais-je utiliser? Devrais-je définir quelque chose comme uw
, sw
(largeur (non) signée) comme un long
si ce n’est pas sous Windows, et sinon faire une vérification de la taille de la CPU cible?
Dans le monde Unix, quelques arrangements étaient possibles pour la taille des nombres entiers et des pointeurs pour les plates-formes 64 bits. ILP64 (en réalité, très peu d’exemples, Cray en est un exemple) et LP64 (pour presque tout le reste). Les acronymes sont "int, long, les pointeurs sont en 64 bits" et "long, les pointeurs sont en 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é le LP64, conformément aux recommandations du groupe Aspen; seuls les systèmes ayant une longue tradition d’exploitation en 64 bits utilisent schème). 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 système différent pour la transition vers 64 bits: LLP64 ("long long, les pointeurs sont en 64 bits"). Cela a le mérite de signifier que les logiciels 32 bits peuvent être recompilés sans modification. Il a le mérite 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 a toujours eu une révision nécessaire; il s'agissait simplement d'un ensemble de révisions différent de celui nécessaire sur les plates-formes Unix.
Si vous concevez votre logiciel autour de noms de type entier indépendants de la plate-forme, utilisez probablement l'en-tête C99 <inttypes.h>
, Qui, lorsque les types sont disponibles sur la plate-forme, fournit, en signature (répertorié) et non signé (non répertorié; préfixe avec u'):
int8_t
- nombres entiers de 8 bitsint16_t
- entiers 16 bitsint32_t
- entiers 32 bitsint64_t
- entiers 64 bitsuintptr_t
- entiers non signés assez gros pour contenir des pointeursintmax_t
- la plus grande taille de nombre entier sur la plate-forme (peut être supérieure à int64_t
)Vous pouvez ensuite coder votre application en utilisant ces types là où cela est important, en faisant très attention aux types de systèmes (qui peuvent être différents). Il existe un type intptr_t
- un type entier signé pour conserver les pointeurs; vous devriez prévoir de ne pas l'utiliser ou de ne l'utiliser que comme résultat d'une soustraction de deux valeurs uintptr_t
(ptrdiff_t
).
Mais, comme le souligne la question (incrédule), il existe différents systèmes pour la taille des types de données entiers sur des machines 64 bits. S'y habituer; le monde ne va pas changer.
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 ayant souffert de la pourriture du lien, je vous propose donc un autre lien qui peut pourrir.
Pour plus d'informations sur les types d'API Windows tels que INT
, LONG
etc., il existe une page sur MSDN:
Les informations sont également disponibles dans divers fichiers d’en-tête Windows tels que WinDef.h
. J'ai énuméré 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é.
Cet article sur MSDN fait référence à un certain nombre d'alias de types (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 de 64 bits, vous pouvez également utiliser UINT64. (Il en va de même pour ULONG et UINT32.) Peut-être que cela sera un peu plus clair?
Microsoft a également défini UINT_PTR et INT_PTR pour des entiers de la même taille qu’un pointeur.
Voici un liste de types spécifiques à Microsoft - cela fait partie de leur référence de pilote, mais je pense que cela est également valable pour la programmation en général.
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 laisser le système de configuration déterminer le bon type pour la taille requise.
Si vous devez 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.