¿Cuál es el tamaño de bits de long en Windows de 64 bits?
No hace mucho, alguien me dijo que long
no hay 64 bits en máquinas de 64 bits y que siempre debería usar int
. Esto no tenía sentido para mí. He visto documentos (como el del sitio oficial de Apple) que dicen que long
efectivamente son 64 bits cuando se compila para una CPU de 64 bits. Busqué lo que había en Windows de 64 bits y encontré
- Windows:
long
yint
siguen teniendo una longitud de 32 bits, y se definen nuevos tipos de datos especiales para enteros de 64 bits.
(de http://www.intel.com/cd/ids/developer/asmo-na/eng/197664.htm?page=2 )
¿Qué debo usar? ¿Debería definir algo como uw
( sw
ancho (sin) firmar) como long
si no estuviera en Windows y, de lo contrario, verificar el tamaño de bits de la CPU de destino?
En el mundo Unix, había algunas disposiciones posibles para los tamaños de números enteros y punteros para plataformas de 64 bits. Los dos más utilizados fueron el ILP64 (en realidad, sólo unos pocos ejemplos de esto; Cray fue uno de ellos) y el LP64 (para casi todo lo demás). Las siglas provienen de 'int, long, los punteros son de 64 bits' y 'largos, los punteros son de 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
El sistema ILP64 se abandonó en favor del LP64 (es decir, casi todos los entrantes posteriores utilizaron LP64, según las recomendaciones del grupo Aspen; sólo los sistemas con una larga tradición de funcionamiento de 64 bits utilizan un esquema diferente). Todos los sistemas Unix modernos de 64 bits utilizan LP64. MacOS X y Linux son sistemas modernos de 64 bits.
Microsoft utiliza un esquema diferente para la transición a 64 bits: LLP64 ("largo, largo, los punteros son de 64 bits"). Esto tiene la ventaja de que el software de 32 bits se puede recompilar sin cambios. Tiene el demérito de ser diferente de lo que hacen los demás y también requiere revisar el código para explotar las capacidades de 64 bits. Siempre fue necesaria una revisión; era simplemente un conjunto diferente de revisiones de las necesarias en las plataformas Unix.
Si diseña su software en torno a nombres de tipos enteros neutrales para la plataforma, probablemente utilice el <inttypes.h>
encabezado C99, que, cuando los tipos están disponibles en la plataforma, proporciona, en formato firmado (listado) y sin firmar (no listado; prefijo con 'u'):
int8_t
- Enteros de 8 bitsint16_t
- Enteros de 16 bitsint32_t
- Enteros de 32 bitsint64_t
- Enteros de 64 bitsuintptr_t
- enteros sin signo lo suficientemente grandes como para contener punterosintmax_t
- mayor tamaño de número entero en la plataforma (puede ser mayor queint64_t
)
Luego puede codificar su aplicación usando estos tipos cuando sea necesario y teniendo mucho cuidado con los tipos de sistemas (que pueden ser diferentes). Hay un intptr_t
tipo: un tipo entero con signo para contener punteros; debes planear no usarlo, o usarlo solo como resultado de una resta de dos uintptr_t
valores ( ptrdiff_t
).
Pero, como señala la pregunta (con incredulidad), existen diferentes sistemas para los tamaños de los tipos de datos enteros en máquinas de 64 bits. Acostumbrarse a él; el mundo no va a cambiar.
No está claro si la pregunta es sobre el compilador de Microsoft C++ o la API de Windows. Sin embargo, no hay ninguna etiqueta [c++], así que supongo que se trata de la API de Windows. Algunas de las respuestas han sufrido enlaces podridos, por lo que proporciono otro enlace que puede pudrirse.
Para obtener información sobre los tipos de API de Windows como INT
, LONG
etc., hay una página en MSDN:
Tipos de datos de Windows
La información también está disponible en varios archivos de encabezado de Windows como WinDef.h
. He enumerado algunos tipos relevantes aquí:
Tipo | S/U | x86 | x64 ----------------------+-----+--------+------ - BYTE, BOOLEANO | U | 8 bits | 8 bits ----------------------+-----+--------+------ - CORTO | S | 16 bits | 16 bits USORTO, PALABRA | U | 16 bits | 16 bits ----------------------+-----+--------+------ - INT, LARGO | 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 ----------------------+-----+--------+------ - LARGO LARGO | S | 64 bits | 64 bits ULONGLONG, QWORD | U | 64 bits | 64 bits
La columna "S/U" indica firmado/sin firmar.
Este artículo en MSDN hace referencia a una serie de alias de tipos (disponibles en Windows) que son un poco más explícitos con respecto a su ancho:
http://msdn.microsoft.com/en-us/library/aa505945.aspx
Por ejemplo, aunque puedes usar ULONGLONG para hacer referencia a un valor integral sin signo de 64 bits, también puedes usar UINT64. (Lo mismo ocurre con ULONG y UINT32.) ¿Quizás sean un poco más claros?
Microsoft también ha definido UINT_PTR e INT_PTR para números enteros que tienen el mismo tamaño que un puntero.
Aquí hay una lista de tipos específicos de Microsoft : es parte de la referencia de sus controladores, pero creo que también es válida para la programación general.
La forma más sencilla de conocerlo para su compilador/plataforma:
#include <iostream>
int main() {
std::cout << sizeof(long)*8 << std::endl;
}
La multiplicación por 8 es para convertir bytes en bits, ya que sizeof devuelve el número de bytes.
Cuando necesita un tamaño particular, suele ser más fácil utilizar uno de los tipos predefinidos de biblioteca. Si eso no es deseable, puede hacer lo que suele ocurrir con el software de autoconf y hacer que el sistema de configuración determine el tipo correcto para el tamaño necesario.