¿Cuál es la diferencia entre un int y un long en C ++?

120

Corrígeme si estoy equivocado,

int es 4 bytes, con un rango de valores de -2,147,483,648 a 2,147,483,647 (2 ^ 31) de
largo es 4 bytes, con un rango de valores de -2,147,483,648 a 2,147,483,647 (2 ^ 31)

¿Cuál es la diferencia en C ++? ¿Pueden usarse indistintamente?

Joel
fuente
En mi VS2005 que se ejecuta en un procesador de 32 bits, el tamaño predeterminado de int es 4 bytes.
Si desea escribir código portátil, considere usar #include <stdint.h>y luego los tipos que indican el tamaño. Ej uint32_t. En una nueva plataforma, solo necesita asegurarse de que stdint.h lo haga bien para esa plataforma en particular y de que su código funcione según lo previsto.
BitTickler

Respuestas:

112

Depende de la implementación.

Por ejemplo, en Windows son iguales, pero, por ejemplo, en los sistemas Alpha, una longitud era de 64 bits, mientras que una int era de 32 bits. Este artículo cubre las reglas para el compilador Intel C ++ en plataformas variables. Para resumir:

  OS           arch           size
Windows       IA-32        4 bytes
Windows       Intel 64     4 bytes
Windows       IA-64        4 bytes
Linux         IA-32        4 bytes
Linux         Intel 64     8 bytes
Linux         IA-64        8 bytes
Mac OS X      IA-32        4 bytes
Mac OS X      Intel 64     8 bytes  
Rob Walker
fuente
Creo que deberíamos considerar combinar esta respuesta (una respuesta por ejemplo) con algunos de los detalles a continuación con respecto al estándar C ++. El borrador de C ++ 0x está en open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2798.pdf y está marcado para que pueda ver las diferencias entre él y la última revisión.
Patrick Johnmeyer
Incluir algo en el orden relativo de tamaño de los tipos produce mucha más información que enumerar tamaños para diferentes plataformas, como @Kevin afirma muy bien. (-1vote)
xtofl
2
Algunos compiladores incluso tienen indicadores que le permiten modificar el tamaño predeterminado de int y long, es decir, forzarlos a 8 o 16, etc. Consulte la documentación del compilador para obtener más detalles.
Martin York
7
NB que estos son los tamaños de largo
rogerdpack
1
Incluya también los tamaños de int.
cegprakash
82

La única garantía que tienes son:

sizeof(char) == 1
sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)

// FROM @KTC. The C++ standard also has:
sizeof(signed char)   == 1
sizeof(unsigned char) == 1

// NOTE: These size are not specified explicitly in the standard.
//       They are implied by the minimum/maximum values that MUST be supported
//       for the type. These limits are defined in limits.h
sizeof(short)     * CHAR_BIT >= 16
sizeof(int)       * CHAR_BIT >= 16
sizeof(long)      * CHAR_BIT >= 32
sizeof(long long) * CHAR_BIT >= 64
CHAR_BIT         >= 8   // Number of bits in a byte

Consulte también: ¿Se longgarantiza que sea de al menos 32 bits?

Martin York
fuente
1
Hmm, esto no es válido, si sizeof (corto)> = sizeof (char) solo sabemos que sizeof (corto)> = 1 (no> = 2), que por cierto se aplica a todos los tipos. De acuerdo con este sizeof (cualquier tipo integral)> = 1. ¿Cuál es cierto, por ejemplo, recuerdo sizeof (int) == 1 en el Z80, pero no hay una garantía más fuerte por mucho tiempo?
Andreas Magnusson
6
3.9.1.2 del estándar C ++ especifica que sizeof (long)> = sizeof (int)> = sizeof (short)> = sizeof (char) 5.3.3.1 del estándar C ++ especifica que sizeof (char), sizeof (unsigned char) , y el tamaño de (carácter firmado) es igual a 1. (cont ...)
KTC
4
(... cont) Los valores máximo y mínimo representables por los tipos integrales se definen como macros en <limits.h> (y por lo tanto <climits>). El anexo E del estándar C (1990), que se incluye por referencia del estándar C ++, especifica las magnitudes mínimas de estas macros. (cont ...)
KTC
4
(... cont) y son (2 ^ 15) -1, (2 ^ 15) -1, (2 ^ 31) -1, para short, int y long respectivamente, que resulta ser el valor como publicado por Martin York en su respuesta aquí si CHAR_BIT es 8 (que también es su valor mínimo).
KTC
2
@Giles: ¿No es eso lo que dije arriba? sizeof (corto) * CHAR_BITS> = 16. Ponga algunas otras cosas. :-)
Martin York
13

Al compilar para x64, la diferencia entre int y long está entre 0 y 4 bytes, dependiendo del compilador que use.

GCC usa el modelo LP64, lo que significa que los ints son de 32 bits, pero los longs son de 64 bits en el modo de 64 bits.

MSVC, por ejemplo, usa el modelo LLP64, lo que significa que tanto los ints como los longs son de 32 bits incluso en el modo de 64 bits.

Adrian
fuente
posiblemente 0 bytes? hmm
rogerdpack
12

La especificación de C ++ en sí (versión antigua pero lo suficientemente buena para esto) deja esto abierto.

Hay cuatro tipos de enteros con signo: ' signed char', ' short int', ' int' y ' long int'. En esta lista, cada tipo proporciona al menos tanto almacenamiento como los que lo preceden en la lista. Las entradas simples tienen el tamaño natural sugerido por la arquitectura del entorno de ejecución *;

[Nota a pie de página: es decir, lo suficientemente grande para contener cualquier valor en el rango de INT_MIN e INT_MAX, como se define en el encabezado <climits>. --- fin foonote]

Kevin Haines
fuente
7

Como señala Kevin Haines, los ints tienen el tamaño natural sugerido por el entorno de ejecución, que debe encajar en INT_MIN e INT_MAX.

El estándar C89 establece que UINT_MAXdebería ser al menos 2 ^ 16-1, USHRT_MAX2 ^ 16-1 y ULONG_MAX2 ^ 32-1. Eso hace un recuento de bits de al menos 16 para short e int, y 32 para long. Para char, establece explícitamente que debe tener al menos 8 bits ( CHAR_BIT). C ++ hereda esas reglas para el archivo limits.h, por lo que en C ++ tenemos los mismos requisitos fundamentales para esos valores. Sin embargo, no debe deducirse que int es al menos de 2 bytes. Teóricamente, char, int y long podrían ser todos de 1 byte, en cuyo caso CHAR_BITdebe ser al menos 32. Solo recuerde que "byte" es siempre del tamaño de un char, por lo que si char es más grande, un byte no solo tiene 8 bits. más.

Johannes Schaub - litb
fuente
No pensé que byteexistiera un tipo de datos en C ++. No es así, ¿verdad? Si lo hace, y bytepuede tener otros tamaños que 8 bits, es puramente estúpido. ¿Por qué lo llamarían byte a menos que sea absolutamente necesariamente de 8 bits?
Alderath
6

Depende de tu compilador. Se le garantiza que un long será al menos tan grande como un int, pero no se le garantiza que lo sea más.

Andru Luvisi
fuente
5

En su mayor parte, el número de bytes y el rango de valores está determinado por la arquitectura de la CPU, no por C ++. Sin embargo, C ++ establece requisitos mínimos, que litb explicó correctamente y Martin York solo cometió algunos errores con.

La razón por la que no puede usar int y long indistintamente es porque no siempre tienen la misma longitud. C se inventó en un PDP-11 donde un byte tenía 8 bits, int tenía dos bytes y podía manejarse directamente mediante instrucciones de hardware. Dado que los programadores de C a menudo necesitaban aritmética de cuatro bytes, se inventó long y eran cuatro bytes, manejados por funciones de biblioteca. Otras máquinas tenían especificaciones diferentes. El estándar C impuso algunos requisitos mínimos.

Programador de Windows
fuente
5

Depender de la implementación del proveedor del compilador de tamaños de tipo primitivos VOLVERÁ a atormentarlo si alguna vez compila su código en otra arquitectura de máquina, sistema operativo o compilador de otro proveedor.

La mayoría de los proveedores de compiladores proporcionan un archivo de encabezado que define tipos primitivos con tamaños de tipo explícitos. Estos tipos primitivos deben usarse siempre que el código pueda potencialmente ser portado a otro compilador (lea esto como SIEMPRE en CADA instancia). Por ejemplo, la mayoría de los compiladores de UNIX tienen int8_t uint8_t int16_t int32_t uint32_t. Microsoft tiene INT8 UINT8 INT16 UINT16 INT32 UINT32. Prefiero el de Borland / CodeGear int8 uint8 int16 uint16 int32 uint32. Estos nombres también dan un pequeño recordatorio del tamaño / rango del valor deseado.

Durante años he usado los nombres de tipos primitivos explícitos de Borland y #includeel siguiente archivo de encabezado C / C ++ (primitive.h) que está destinado a definir los tipos primitivos explícitos con estos nombres para cualquier compilador C / C ++ (este archivo de encabezado podría no cubrir todos los compilador pero cubre varios compiladores que he usado en Windows, UNIX y Linux, tampoco (todavía) define tipos de 64 bits).

#ifndef primitiveH
#define primitiveH
// Header file primitive.h
// Primitive types
// For C and/or C++
// This header file is intended to define a set of primitive types
// that will always be the same number bytes on any operating operating systems
// and/or for several popular C/C++ compiler vendors.
// Currently the type definitions cover:
// Windows (16 or 32 bit)
// Linux
// UNIX (HP/US, Solaris)
// And the following compiler vendors
// Microsoft, Borland/Imprise/CodeGear, SunStudio,  HP/UX
// (maybe GNU C/C++)
// This does not currently include 64bit primitives.
#define float64 double
#define float32 float
// Some old C++ compilers didn't have bool type
// If your compiler does not have bool then add   emulate_bool
// to your command line -D option or defined macros.
#ifdef emulate_bool
#   ifdef TVISION
#     define bool int
#     define true 1
#     define false 0
#   else
#     ifdef __BCPLUSPLUS__
      //BC++ bool type not available until 5.0
#        define BI_NO_BOOL
#        include <classlib/defs.h>
#     else
#        define bool int
#        define true 1
#        define false 0
#     endif
#  endif
#endif
#ifdef __BCPLUSPLUS__
#  include <systypes.h>
#else
#  ifdef unix
#     ifdef hpux
#        include <sys/_inttypes.h>
#     endif
#     ifdef sun
#        include <sys/int_types.h>
#     endif
#     ifdef linux
#        include <idna.h>
#     endif
#     define int8 int8_t
#     define uint8 uint8_t
#     define int16 int16_t
#     define int32 int32_t
#     define uint16 uint16_t
#     define uint32 uint32_t
#  else
#     ifdef  _MSC_VER
#        include <BaseTSD.h>
#        define int8 INT8
#        define uint8 UINT8
#        define int16 INT16
#        define int32 INT32
#        define uint16 UINT16
#        define uint32 UINT32
#     else
#        ifndef OWL6
//          OWL version 6 already defines these types
#           define int8 char
#           define uint8 unsigned char
#           ifdef __WIN32_
#              define int16 short int
#              define int32 long
#              define uint16 unsigned short int
#              define uint32 unsigned long
#           else
#              define int16 int
#              define int32 long
#              define uint16 unsigned int
#              define uint32 unsigned long
#           endif
#        endif
#      endif
#  endif
#endif
typedef int8   sint8;
typedef int16  sint16;
typedef int32  sint32;
typedef uint8  nat8;
typedef uint16 nat16;
typedef uint32 nat32;
typedef const char * cASCIIz;    // constant null terminated char array
typedef char *       ASCIIz;     // null terminated char array
#endif
//primitive.h
Roger Nelson
fuente
C99 exige que los typdefs que se parecen a int32_t, uint64_t, etc. estén definidos por el compilador y tengan exactamente tantos bits como sugiere el nombre. La mayoría de los compiladores de C ++ (incluido g ++) le permitirán utilizar estas constantes en código C ++.
rmeador
5

El estándar C ++ dice así:

3.9.1, §2:

Hay cinco tipos de enteros con signo: "firmado char", "short int", "int", "long int" y "long long int". En esta lista, cada tipo proporciona al menos tanto almacenamiento como los que lo preceden en la lista. Los planos simples tienen el tamaño natural sugerido por la arquitectura del entorno de ejecución (44); los otros tipos de enteros con signo se proporcionan para satisfacer necesidades especiales.

(44) es decir, lo suficientemente grande para contener cualquier valor en el rango de INT_MIN e INT_MAX, como se define en el encabezado <climits> .

La conclusión: depende de la arquitectura en la que esté trabajando. Cualquier otra suposición es falsa.

Jérôme Radix
fuente