Quelle est la différence entre un int et un long en C ++?

120

Corrigez-moi si je me trompe,

int est de 4 octets, avec une plage de valeurs de -2,147,483,648 à 2,147,483,647 (2 ^ 31)
long est de 4 octets, avec une plage de valeurs de -2,147,483,648 à 2,147,483,647 (2 ^ 31)

Quelle est la différence en C ++? Peuvent-ils être utilisés de manière interchangeable?

Joël
la source
Dans mon VS2005 fonctionnant sur un processeur 32 bits, la taille par défaut de int est de 4 octets.
Si vous voulez écrire du code portable, pensez à utiliser #include <stdint.h>et ensuite les types qui indiquent la taille. Par exemple uint32_t. Sur une nouvelle plate-forme, il vous suffit de vous assurer que stdint.h convient parfaitement à cette plate-forme particulière et que votre code fonctionne comme prévu.
BitTickler

Réponses:

112

Cela dépend de la mise en œuvre.

Par exemple, sous Windows, ce sont les mêmes, mais par exemple sur les systèmes Alpha, un long était de 64 bits alors qu'un int était de 32 bits. Cet article couvre les règles du compilateur Intel C ++ sur les plates-formes variables. Résumer:

  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
la source
Je pense que nous devrions envisager de combiner cette réponse (une réponse par exemple) avec certains des détails ci-dessous concernant la norme C ++. Le brouillon pour C ++ 0x se trouve sur open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2798.pdf et il est balisé pour que vous puissiez voir les différences entre lui et la dernière version.
Patrick Johnmeyer
Inclure quelque chose dans l'ordre de taille relative des types donne beaucoup plus d'informations que d'énumérer les tailles pour différentes plates-formes - comme @Kevin déclare si bien. (-1vote)
xtofl
2
Certains compilateurs ont même des indicateurs qui vous permettent de modifier la taille par défaut de int et long ie les forcer à 8 ou 16 etc. Consultez la documentation du compilateur pour plus de détails.
Martin York
7
NB que ce sont les tailles de long
rogerdpack
1
Veuillez également inclure les tailles de int.
cegprakash
82

Les seules garanties dont vous disposez sont:

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

Voir aussi: Est-il longgaranti avoir au moins 32 bits?

Martin York
la source
1
Hmm, cela ne tient pas, si sizeof (short)> = sizeof (char), nous ne savons que sizeof (short)> = 1 (pas> = 2), ce qui vaut pour tous les types. Selon cette sizeof (tout type intégral)> = 1. Ce qui est vrai, par exemple je me souviens de sizeof (int) == 1 sur le Z80, mais n'y a-t-il pas de garantie plus solide pour longtemps?
Andreas Magnusson
6
3.9.1.2 du standard C ++ spécifier que sizeof (long)> = sizeof (int)> = sizeof (short)> = sizeof (char) 5.3.3.1 du standard C ++ spécifier que sizeof (char), sizeof (unsigned char) , et sizeof (signe signé) est égal à 1. (suite ...)
KTC
4
(... suite) Les valeurs maximum et minimum représentables par les types intégraux sont définies comme des macros dans <limits.h> (et donc <climits>). L'annexe E de la norme C (1990), qui sont incluses par référence à partir de la norme C ++, spécifie les grandeurs minimales de ces macros. (suite ...)
KTC
4
(... cont) et ils sont (2 ^ 15) -1, (2 ^ 15) -1, (2 ^ 31) -1, respectivement pour short, int et long, ce qui correspond à la valeur posté par Martin York dans sa réponse ici si CHAR_BIT vaut 8 (qui est aussi sa valeur minimale).
KTC
2
@Giles: N'est-ce pas ce que j'ai dit ci-dessus? sizeof (short) * CHAR_BITS> = 16. Plust quelques autres choses. :-)
Martin York
13

Lors de la compilation pour x64, la différence entre int et long se situe entre 0 et 4 octets, selon le compilateur que vous utilisez.

GCC utilise le modèle LP64, ce qui signifie que les entiers sont 32 bits mais les longs sont 64 bits en mode 64 bits.

MSVC, par exemple, utilise le modèle LLP64, ce qui signifie que les entiers et les longs sont 32 bits même en mode 64 bits.

Adrian
la source
éventuellement 0 octets? hmm
rogerdpack
12

La spécification C ++ elle-même (ancienne version mais suffisante pour cela) laisse cela ouvert.

Il existe quatre types d'entiers signés: « signed char», « short int», « int» et « long int». Dans cette liste, chaque type fournit au moins autant de stockage que ceux qui le précèdent dans la liste. Les entiers simples ont la taille naturelle suggérée par l'architecture de l'environnement d'exécution *;

[Note de bas de page: c'est-à-dire suffisamment grand pour contenir n'importe quelle valeur dans la plage de INT_MIN et INT_MAX, comme défini dans l'en-tête <climits>. --- fin foonote]

Kevin Haines
la source
7

Comme le souligne Kevin Haines, les entiers ont la taille naturelle suggérée par l'environnement d'exécution, qui doit tenir dans INT_MIN et INT_MAX.

La norme C89 stipule qu'il UINT_MAXdoit être au moins 2 ^ 16-1, USHRT_MAX2 ^ 16-1 et ULONG_MAX2 ^ 32-1. Cela fait un nombre de bits d'au moins 16 pour court et int, et 32 ​​pour long. Pour char, il indique explicitement qu'il doit avoir au moins 8 bits ( CHAR_BIT). C ++ hérite de ces règles pour le fichier limits.h, donc en C ++, nous avons les mêmes exigences fondamentales pour ces valeurs. Vous ne devez cependant pas en déduire que int est au moins 2 octets. Théoriquement, char, int et long pourraient tous être de 1 octet, auquel cas il CHAR_BITdoit être d'au moins 32. Rappelez-vous simplement que "byte" a toujours la taille d'un char, donc si char est plus grand, un octet n'est pas seulement de 8 bits. plus.

Johannes Schaub - litb
la source
Je ne pensais pas qu'un bytetype de données existe en C ++. Ce n'est pas le cas, n'est-ce pas? Si c'est le cas, et qu'un bytepeut avoir d'autres tailles que 8 bits, c'est purement stupide. Pourquoi l'appelleraient-ils un octet à moins qu'il ne s'agisse absolument nécessairement de 8 bits?
Alderath
6

Cela dépend de votre compilateur. Vous avez la garantie qu'un long sera au moins aussi grand qu'un int, mais vous n'êtes pas assuré qu'il le sera plus longtemps.

Andru Luvisi
la source
5

Pour la plupart, le nombre d'octets et la plage de valeurs sont déterminés par l'architecture du processeur et non par C ++. Cependant, C ++ définit des exigences minimales, que litb a bien expliqué et Martin York n'a commis que quelques erreurs avec.

La raison pour laquelle vous ne pouvez pas utiliser int et long de manière interchangeable est qu'ils ne sont pas toujours de la même longueur. C a été inventé sur un PDP-11 où un octet avait 8 bits, int était de deux octets et pouvait être manipulé directement par des instructions matérielles. Étant donné que les programmeurs C avaient souvent besoin d'arithmétique sur quatre octets, long a été inventé et il était de quatre octets, géré par des fonctions de bibliothèque. D'autres machines avaient des spécifications différentes. La norme C imposait des exigences minimales.

Programmeur Windows
la source
5

S'appuyer sur l'implémentation par le fournisseur du compilateur des tailles de types primitifs reviendra vous hanter si jamais vous compilez votre code sur une autre architecture de machine, un autre système d'exploitation ou un compilateur d'un autre fournisseur.

La plupart des fournisseurs de compilateurs fournissent un fichier d'en-tête qui définit les types primitifs avec des tailles de type explicites. Ces types primitifs doivent être utilisés chaque fois que du code peut être potentiellement porté vers un autre compilateur (lisez ceci comme TOUJOURS dans CHAQUE instance). Par exemple, la plupart des compilateurs UNIX ont int8_t uint8_t int16_t int32_t uint32_t. Microsoft a INT8 UINT8 INT16 UINT16 INT32 UINT32. Je préfère Borland / CodeGear int8 uint8 int16 uint16 int32 uint32. Ces noms donnent également un petit rappel de la taille / plage de la valeur prévue.

Pendant des années, j'ai utilisé les noms de types primitifs explicites de Borland et #includele fichier d'en-tête C / C ++ suivant (primitive.h) qui est destiné à définir les types primitifs explicites avec ces noms pour tout compilateur C / C ++ (ce fichier d'en-tête peut ne pas couvrir tous les compilateur mais il couvre plusieurs compilateurs que j'ai utilisés sous Windows, UNIX et Linux, il ne définit pas (encore) les types 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
la source
C99 exige que les typdefs qui ressemblent à int32_t, uint64_t, etc. soient définis par le compilateur et aient exactement autant de bits que son nom l'indique. La plupart des compilateurs C ++ (y compris g ++) vous permettront d'utiliser ces constantes dans le code C ++.
rmeador
5

Le standard C ++ le dit comme ceci:

3.9.1, §2:

Il existe cinq types d'entiers signés: "signed char", "short int", "int", "long int" et "long long int". Dans cette liste, chaque type fournit au moins autant de stockage que ceux qui le précèdent dans la liste. Les ints simples ont la taille naturelle suggérée par l'architecture de l'environnement d'exécution (44); les autres types d'entiers signés sont fournis pour répondre à des besoins particuliers.

(44) c'est-à-dire suffisamment grand pour contenir n'importe quelle valeur dans la plage de INT_MIN et INT_MAX, comme défini dans l'en-tête <climits> .

La conclusion: cela dépend de l'architecture sur laquelle vous travaillez. Toute autre hypothèse est fausse.

Jérôme Radix
la source