Qual é a diferença entre um int e um long em C ++?

120

Corrija-me se eu estiver errada,

int é de 4 bytes, com um intervalo de valores de -2.147.483.648 a 2.147.483.647 (2 ^ 31) de
comprimento é de 4 bytes, com um intervalo de valores de -2.147.483.648 a 2.147.483.647 (2 ^ 31)

Qual é a diferença em C ++? Eles podem ser usados ​​de forma intercambiável?

Joel
fonte
No meu VS2005 em execução no processador de 32 bits, o tamanho padrão de int é 4 bytes.
Se você deseja escrever código portátil, considere usar #include <stdint.h>e, em seguida, os tipos que informam o tamanho. Por exemplo uint32_t. Em uma nova plataforma, você só precisa garantir que o stdint.h acerte nessa plataforma específica e seu código funcione conforme o esperado.
BitTickler 25/06

Respostas:

112

É dependente da implementação.

Por exemplo, no Windows, eles são os mesmos, mas, por exemplo, nos sistemas Alpha, um comprimento era de 64 bits, enquanto um int era de 32 bits. Este artigo aborda as regras para o compilador Intel C ++ em plataformas variáveis. 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
fonte
Penso que devemos considerar combinar esta resposta (uma resposta por exemplo) com alguns dos detalhes abaixo sobre o padrão C ++. O rascunho do C ++ 0x está em open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2798.pdf e está marcado para que você possa ver as diferenças entre ele e a última rev.
31420 Patrick Johnmeyer
Incluir algo na ordem relativa de tamanho dos tipos gera muito mais informações do que enumerar tamanhos para diferentes plataformas - como @Kevin afirma tão bem. (-1vote)
xtofl 7/11/08
2
Alguns compiladores têm até sinalizadores que permitem modificar o tamanho padrão de int e long, ou seja, forçá-los a 8 ou 16 etc. Consulte a documentação do compilador para obter detalhes.
Martin Iorque
7
NB que estes são os tamanhos de long
rogerdpack
1
Inclua também os tamanhos de int.
Cegprakash
82

A única garantia que você tem é:

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

Veja também: É longgarantido que tenha pelo menos 32 bits?

Martin York
fonte
1
Hmm, isso não vale, se sizeof (short)> = sizeof (char) sabemos apenas que sizeof (short)> = 1 (não> = 2), o que é válido para todos os tipos. De acordo com este sizeof (qualquer tipo integral)> = 1. O que é verdade, por exemplo, lembro-me de sizeof (int) == 1 no Z80, mas não há garantia mais forte por muito tempo?
Andreas Magnusson 7/08
6
3.9.1.2 do padrão C ++ especifica que sizeof (long)> = sizeof (int)> = sizeof (short)> = sizeof (char) 5.3.3.1 do padrão C ++ especifica que sizeof (char), sizeof (char não assinado) e sizeof (caractere assinado) é igual a 1. (cont ...)
KTC
4
(... cont) Os valores máximos e mínimos representáveis ​​pelos tipos integrais são definidos como macros em <limits.h> (e, portanto, <climits>). O anexo E do padrão C (1990), incluído por referência no padrão C ++, especifica as magnitudes mínimas dessas macros. (cont ...)
KTC
4
(... cont) e são (2 ^ 15) -1, (2 ^ 15) -1, (2 ^ 31) -1, abreviado, int e longo, respectivamente, o que resulta ser o valor como postado por Martin York em sua resposta aqui se CHAR_BIT for 8 (que também é seu valor mínimo).
KTC
2
@ Giles: Não foi isso que eu disse acima? sizeof (short) * CHAR_BITS> = 16. Resolva algumas outras coisas. :-)
Martin York
13

Ao compilar para x64, a diferença entre int e long está entre 0 e 4 bytes, dependendo do compilador usado.

O GCC usa o modelo LP64, o que significa que as entradas são de 32 bits, mas os compridos são de 64 bits no modo de 64 bits.

A MSVC, por exemplo, usa o modelo LLP64, o que significa que ints e longs são 32 bits, mesmo no modo de 64 bits.

Adrian
fonte
possivelmente 0 bytes? hmm
rogerdpack
12

A própria especificação C ++ (versão antiga, mas boa o suficiente para isso) deixa em aberto.

Existem quatro tipos de números inteiros assinados: ' signed char', ' short int', ' int' e ' long int'. Nesta lista, cada tipo fornece pelo menos a quantidade de armazenamento que os anteriores à lista. Ints simples têm o tamanho natural sugerido pela arquitetura do ambiente de execução *;

[Nota de rodapé: ou seja, grande o suficiente para conter qualquer valor no intervalo de INT_MIN e INT_MAX, conforme definido no cabeçalho <climits>. --- foonote final]

Kevin Haines
fonte
7

Como Kevin Haines salienta, as entradas têm o tamanho natural sugerido pelo ambiente de execução, que deve se encaixar em INT_MIN e INT_MAX.

O padrão C89 afirma que UINT_MAXdeve ser pelo menos 2 ^ 16-1, USHRT_MAX2 ^ 16-1 e ULONG_MAX2 ^ 32-1. Isso faz uma contagem de bits de pelo menos 16 para short e int e 32 por muito tempo. Para char, afirma explicitamente que deve ter pelo menos 8 bits ( CHAR_BIT). O C ++ herda essas regras para o arquivo limits.h, portanto, no C ++, temos os mesmos requisitos fundamentais para esses valores. No entanto, você não deve derivar que int seja de pelo menos 2 bytes. Teoricamente, char, int e long podem ter 1 byte, e nesse caso CHAR_BITdeve ter pelo menos 32. Lembre-se de que "byte" é sempre do tamanho de um char; portanto, se char for maior, um byte não terá apenas 8 bits Mais.

Johannes Schaub - litb
fonte
Eu não acho que byteexista um tipo de dados em C ++. Não, não é? Se isso acontecer, e um bytepode ter outros tamanhos além de 8 bits, é puramente estúpido. Por que eles chamariam de byte, a menos que seja absolutamente necessariamente de 8 bits?
Alderath
6

Depende do seu compilador. Você tem a garantia de que um longo será pelo menos tão grande quanto um int, mas você não tem a garantia de que será mais.

Andru Luvisi
fonte
5

Na maioria das vezes, o número de bytes e o intervalo de valores são determinados pela arquitetura da CPU e não pelo C ++. No entanto, o C ++ define requisitos mínimos, o que litb explicou corretamente e Martin York cometeu apenas alguns erros.

A razão pela qual você não pode usar int e long intercambiavelmente é porque eles nem sempre têm o mesmo comprimento. C foi inventado em um PDP-11, onde um byte tinha 8 bits, int tinha dois bytes e poderia ser tratado diretamente por instruções de hardware. Como os programadores C geralmente precisavam de aritmética de quatro bytes, o tempo foi inventado e eram quatro bytes, manipulados pelas funções da biblioteca. Outras máquinas tinham especificações diferentes. O padrão C impôs alguns requisitos mínimos.

Programador do Windows
fonte
5

Confiar na implementação de tamanhos de tipos primitivos do fornecedor do compilador voltará a assombrá-lo se você compilar seu código em outra arquitetura de máquina, SO ou compilador de outro fornecedor.

A maioria dos fornecedores de compiladores fornece um arquivo de cabeçalho que define tipos primitivos com tamanhos explícitos. Esses tipos primitivos devem ser usados ​​sempre que o código for potencialmente portado para outro compilador (leia-o como SEMPRE em TODAS as instâncias). Por exemplo, a maioria dos compiladores UNIX possui int8_t uint8_t int16_t int32_t uint32_t. Microsoft tem INT8 UINT8 INT16 UINT16 INT32 UINT32. Eu prefiro o Borland / CodeGear int8 uint8 int16 uint16 int32 uint32. Esses nomes também fornecem um pequeno lembrete do tamanho / intervalo do valor pretendido.

Por anos, usei os nomes explícitos de tipos primitivos da Borland e #includeo seguinte arquivo de cabeçalho C / C ++ (primitive.h), que tem como objetivo definir os tipos primitivos explícitos com esses nomes para qualquer compilador C / C ++ (esse arquivo de cabeçalho pode, na verdade, não cobrir todos os compilador, mas abrange vários compiladores que usei no Windows, UNIX e Linux, mas ainda não 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
fonte
O C99 exige que typdefs parecidos com int32_t, uint64_t, etc, sejam definidos pelo compilador e tenham exatamente tantos bits quanto o nome sugere. A maioria dos compiladores C ++ (incluindo g ++) permitirá que você use essas constantes no código C ++.
Rmeador
5

O padrão C ++ diz assim:

3.9.1, §2:

Existem cinco tipos de números inteiros assinados: "caractere assinado", "int curto", "int", "int longo" e "int longo longo". Nesta lista, cada tipo fornece pelo menos a quantidade de armazenamento que os anteriores à lista. Ints simples têm o tamanho natural sugerido pela arquitetura do ambiente de execução (44); os outros tipos de números inteiros assinados são fornecidos para atender a necessidades especiais.

(44), ou seja, grande o suficiente para conter qualquer valor no intervalo de INT_MIN e INT_MAX, conforme definido no cabeçalho <climits> .

A conclusão: depende de qual arquitetura você está trabalhando. Qualquer outra suposição é falsa.

Jérôme Radix
fonte