web-dev-qa-db-fra.com

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

Corrigez-moi si je me trompe,

int est 4 octets, avec une plage de valeurs allant de -2 147 483 648 à 2 147 483 647 (2 ^ 31)
est long de 4 octets, avec une plage de valeurs allant 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?

111
Joel

Cela dépend de la mise en œuvre.

Par exemple, sous Windows, ils sont identiques, mais sur les systèmes Alpha, par exemple, une longueur était de 64 bits alors qu'un int était de 32 bits. Cet article couvre les règles du compilateur Intel C++ sur des 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  
101
Rob Walker

La seule garantie que vous avez est:

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 garanti que long aura au moins 32 bits?

78
Martin York

Lors de la compilation pour x64, la différence entre int et long se situe entre 0 et 4 octets, en fonction du compilateur utilisé.

GCC utilise le modèle LP64, ce qui signifie que les entrées sont en 32 bits mais que les longueurs sont en 64 bits en mode 64 bits.

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

13
Adrian

Le spécification C++ elle-même (ancienne version, mais assez bonne 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. Plain ints ont la taille naturelle suggérée par l'architecture de l'environnement d'exécution *;

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

12
Kevin Haines

Comme le souligne Kevin Haines, les tailles internes 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 que UINT_MAX devrait être au moins 2 ^ 16-1, USHRT_MAX 2 ^ 16-1 et ULONG_MAX 2 ^ 32-1. Cela fait un nombre de bits d'au moins 16 pour court et int, et 32 ​​pour longtemps. Pour char, il est explicitement indiqué qu'il doit avoir au moins 8 bits (CHAR_BIT). C++ hérite de ces règles pour le fichier limits.h. En C++, nous avons donc les mêmes exigences fondamentales pour ces valeurs. Vous devriez cependant not en déduire que int est au moins 2 octets. Théoriquement, char, int et long pourraient tous avoir un octet, auquel cas CHAR_BIT doit être au moins égal à 32. Rappelez-vous simplement que "octet" a toujours la taille d'un caractère. Ainsi, si le caractère est plus grand, un octet ne représente plus que 8 bits.

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

6
Andru Luvisi

Dans la plupart des cas, le nombre d'octets et la plage de valeurs sont déterminés par l'architecture de la CPU, et non par C++. Cependant, C++ définit les exigences minimales, ce que litb a expliqué correctement et que Martin York n'a fait que quelques erreurs avec.

La raison pour laquelle vous ne pouvez pas utiliser inter 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 deux octets et pouvait être manipulé directement par des instructions matérielles. Comme les programmeurs C avaient souvent besoin de l'arithmétique de quatre octets, une longue invention a été inventée. Il s'agissait de quatre octets, gérés par des fonctions de bibliothèque. D'autres machines avaient des spécifications différentes. La norme C impose certaines exigences minimales.

5

En vous reposant sur l'implémentation par le fournisseur du compilateur des tailles de type primitif, vous reviendrez vous hanter si vous compilez votre code sur une autre architecture de machine, un système d'exploitation ou le 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 potentiellement être porté vers un autre compilateur (lisez ceci comme TOUJOURS dans TOUS les cas). 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's int8 uint8 int16 uint16 int32 uint32. Ces noms rappellent également un peu la taille/plage de la valeur souhaitée.

Pendant des années, j'ai utilisé les noms de types primitifs explicites de Borland et #include le fichier d’en-tête C/C++ suivant (primitive.h) destiné à définir les types primitifs explicites avec ces noms pour n’importe quel compilateur C/C++ (ce fichier d’en-tête ne couvre peut-être pas tous les compilateurs, mais 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
5
Roger Nelson

Le C++ Standard le dit comme ceci:

3.9.1, §2:

Il existe cinq types d'entiers signés: "char signé", "int court", "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. Plain ints 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 assez 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.

4
Jérôme Radix