Qual è la dimensione in bit di long su Windows a 64 bit?


137

Non molto tempo fa, qualcuno mi ha detto che longnon sono 64 bit su macchine a 64 bit e che dovrei sempre usare int. Questo non aveva senso per me. Ho visto documenti (come quello sul sito ufficiale di Apple) che dicono che in longeffetti sono 64 bit durante la compilazione per una CPU a 64 bit. Ho cercato quello che era su Windows a 64 bit e ho trovato

  • Windows: longe intrimangono a 32 bit di lunghezza e vengono definiti nuovi tipi di dati speciali per numeri interi a 64 bit.

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

Cosa dovrei usare? Devo definire qualcosa di simile uw, sw((un) di larghezza firmato) come longse non su Windows, e in caso contrario fare un controllo sul Bitsize CPU di destinazione?


Su Windows con MSVC ++ int e long sono a 32 bit: msdn.microsoft.com/en-us/library/3b2e7499.aspx . Tuttavia, per consentire ad esempio ai vettori di memorizzare più di 4G di articoli, size_t è 64 bit. Quindi è necessario utilizzare int64_t anziché int per iterare, ad esempio, vettori che possono contenere più di elementi 4G.
Serge Rogatch,


@SergeRogatch dovrebbero usare size_to un tipo di iteratore per iterare, no intoppureint64_t
phuclv,

2
@ LưuVĩnhPhúc, con size_tesso diventa difficile numeri quasi negativi, perché size_tnon è firmato. Quindi, for(size_t i=0; i<v.size()-2; i++)non riesce per dimensioni vettore 0 e 1. Un altro esempio: for(size_t i=v.size()-1; i>=0; i--).
Serge Rogatch,

2
Se stai facendo matematica sui puntatori (cioè con i size_tvalori, il risultato dovrebbe essere mantenuto in una variabile di ptrdiff_ttipo - che è progettato per essere abbastanza grande da contenere un tale risultato ed è un tipo firmato proprio per questo motivo!)
SlySven

Risposte:


261

Nel mondo Unix, c'erano alcune possibili disposizioni per le dimensioni di numeri interi e puntatori per piattaforme a 64 bit. I due maggiormente utilizzati erano ILP64 (in realtà, solo pochi esempi di questo; Cray era uno di questi) e LP64 (per quasi tutto il resto). Gli acronimi provengono da "int, long, puntatori sono a 64 bit" e "long, puntatori sono a 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

Il sistema ILP64 è stato abbandonato a favore di LP64 (ovvero, quasi tutti i partecipanti successivi hanno utilizzato LP64, in base alle raccomandazioni del gruppo Aspen; solo i sistemi con una lunga tradizione di operazioni a 64 bit utilizzano uno schema diverso). Tutti i moderni sistemi Unix a 64 bit utilizzano LP64. MacOS X e Linux sono entrambi moderni sistemi a 64 bit.

Microsoft utilizza uno schema diverso per la transizione a 64 bit: LLP64 ('long long, pointers are 64-bit'). Questo ha il merito di significare che il software a 32 bit può essere ricompilato senza modifiche. Ha il demerito di essere diverso da quello che fanno tutti gli altri, e richiede anche che il codice venga rivisto per sfruttare le capacità a 64 bit. C'era sempre la revisione necessaria; era solo una serie diversa di revisioni da quelle necessarie sulle piattaforme Unix.

Se si progetta il proprio software attorno a nomi di numeri interi neutri per la piattaforma, probabilmente usando l' <inttypes.h>intestazione C99 , che, quando i tipi sono disponibili sulla piattaforma, fornisce, con segno (elencato) e non firmato (non elencato; prefisso con 'u'):

  • int8_t - Numeri interi a 8 bit
  • int16_t - Numeri interi a 16 bit
  • int32_t - Numeri interi a 32 bit
  • int64_t - Numeri interi a 64 bit
  • uintptr_t - numeri interi senza segno abbastanza grandi da contenere puntatori
  • intmax_t- dimensione massima dell'intero sulla piattaforma (potrebbe essere maggiore di int64_t)

È quindi possibile codificare l'applicazione utilizzando questi tipi dove è importante e facendo molta attenzione ai tipi di sistema (che potrebbero essere diversi). Esiste un intptr_ttipo: un tipo intero con segno per contenere i puntatori; dovresti pianificare di non usarlo o di usarlo solo come risultato di una sottrazione di due uintptr_tvalori ( ptrdiff_t).

Ma, come sottolinea la domanda (incredulo), esistono sistemi diversi per le dimensioni dei tipi di dati interi su macchine a 64 bit. Abituarsi ad esso; il mondo non cambierà.


12
Per coloro che sono in circolazione da abbastanza tempo, la transizione a 64 bit ha alcuni parallelismi con la transizione da 16 a 32 bit della metà degli anni '80. C'erano computer IL32 e altri L32 (adattando la nuova notazione al vecchio problema). A volte 'int' era a 16 bit, a volte a 32 bit.
Jonathan Leffler,

4
Non dimenticare che questo vale solo per le lingue C-ish. Altri hanno specifiche più sanitarie in cui a) allo scrittore del compilatore non è consentito scegliere la dimensione dei tipi di dati volenti o nolenti b) la rappresentazione fisica dei tipi di dati non "perde" o c) gli interi sono sempre infinitamente grandi.
Jörg W Mittag,

2
Vero - ma per quelle lingue che specificano il comportamento, non c'è un problema in primo luogo. Ad esempio, Java ha un "long", ma la dimensione è fissa (64-bit?), Su tutte le piattaforme. Quindi, non ci sono problemi di porting su una macchina a 64 bit; la dimensione non cambia.
Jonathan Leffler,

17
@TomFobear: ILP64 presenta un grosso problema: come si chiama il tipo a 32 bit? Oppure, se si chiama il tipo a 32 bit short, come si chiama il tipo a 16 bit? E se chiami il tipo a 16 bit charper UTF-16 ecc., Come chiami il tipo a 8 bit? Quindi, l'uso di LP64 ti lascia con 8-bit char, 16-bit short, 32-bit int, 64-bit long, con spazio per l'espansione verso l'alto a 128-bit long longquando (se?) Diventa rilevante. Dopodiché, hai più poteri di 256 di quanti ne abbia i nomi in C (beh, suppongo che potresti avere un 256-bit intmax_t, e solo allora finisci). C'è merito a LP64.
Jonathan Leffler,

2
Forse questo è ovvio per voi ragazzi, ma penso che valga la pena notare che C # usa numeri interi diversi da tutto il resto. Recentemente mi sono imbattuto nell'interfaccia con una DLL poiché C # utilizza longs a 64 bit ( msdn.microsoft.com/en-us/library/ms173105.aspx ).
Compholio,

57

Non è chiaro se la domanda riguarda il compilatore Microsoft C ++ o l'API di Windows. Tuttavia, non esiste un tag [c ++], quindi suppongo si tratti dell'API di Windows. Alcune delle risposte hanno sofferto del marciume dei link, quindi sto fornendo un altro link che può marcire.


Per informazioni sui tipi di API di Windows come INT, LONGecc. , Esiste una pagina su MSDN:

Tipi di dati di Windows

Le informazioni sono disponibili anche in vari file di intestazione di Windows come WinDef.h. Ho elencato alcuni tipi rilevanti qui:

Digita | S / U | x86 | x64
---------------------------- + ----- + -------- + ------ -
BYTE, BOOLEAN | U | 8 bit | 8 bit
---------------------------- + ----- + -------- + ------ -
CORTO | S | 16 bit | 16 bit
USHORT, WORD | U | 16 bit | 16 bit
---------------------------- + ----- + -------- + ------ -
INT, LUNGO | 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
---------------------------- + ----- + -------- + ------ -
LONGLONG | S | 64 bit | 64 bit
ULONGLONG, QWORD | U | 64 bit | 64 bit

La colonna "S / U" indica firmato / non firmato.


4

Questo articolo su MSDN fa riferimento a una serie di alias di tipi (disponibili su Windows) che sono un po 'più espliciti rispetto alla loro larghezza:

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

Ad esempio, sebbene sia possibile utilizzare ULONGLONG per fare riferimento a un valore integrale senza segno a 64 bit, è anche possibile utilizzare UINT64. (Lo stesso vale per ULONG e UINT32.) Forse questi saranno un po 'più chiari?


1
C'è qualche garanzia che uint32_t e DWORD siano intercambiabili? Non è difficile immaginare che potrebbero non essere [ad esempio se il primo è un 32-bit inte il secondo un 32-bit long, gcc assumerebbe che un puntatore a un tipo non sarebbe in grado di alias l'altro nonostante le loro rappresentazioni corrispondenti].
supercat,

4

Microsoft ha anche definito UINT_PTR e INT_PTR per numeri interi che hanno le stesse dimensioni di un puntatore.

Ecco un elenco di tipi specifici di Microsoft : fa parte del riferimento del loro driver, ma credo che sia valido anche per la programmazione generale.


2

Il modo più semplice per conoscerlo per il tuo compilatore / piattaforma:

#include <iostream>

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

La moltiplicazione per 8 è di ottenere bit da byte.

Quando è necessaria una dimensione particolare, è spesso più semplice utilizzare uno dei tipi predefiniti di una libreria. Se ciò non è desiderabile, è possibile fare ciò che spesso accade con il software autoconf e fare in modo che il sistema di configurazione determini il tipo giusto per le dimensioni necessarie.


4
Non importa, ma i byte a 8 bit non fanno effettivamente parte delle specifiche C (clausole 3.6 e 5.2.4.2.1 dello standard C). Sebbene sia difficile trovare una macchina in cui non c'erano 8 bit, è possibile controllare LONG_BIT per vedere quanto è grande il tipo di dati lungo.
Andres,

Naturalmente, hai ragione, dipende dall'architettura ("unità di archiviazione dei dati indirizzabile abbastanza grande da contenere qualsiasi membro del set di caratteri di base dell'ambiente di esecuzione"), ma le architetture più comunemente utilizzate equivalgono a 8 bit.
Paul de Vrieze,

Ma l'OP non ha chiesto del suo compilatore / piattaforma; ha chiesto specificamente di Windows a 64 bit - presumibilmente perché non ha un comodo accesso a un sistema Windows a 64 bit su cui testare.
Quuxplusone,


-2

Se devi usare numeri interi di una certa lunghezza, probabilmente dovresti usare alcune intestazioni indipendenti dalla piattaforma per aiutarti. Boost è un buon posto da guardare.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.