Qual è la differenza tra un int e un long in C ++?


120

Correggimi se sbaglio

int è di 4 byte, con un intervallo di valori da -2.147.483.648 a 2.147.483.647 (2 ^ 31),
lungo 4 byte, con un intervallo di valori da -2.147.483.648 a 2.147.483.647 (2 ^ 31)

Qual è la differenza in C ++? Possono essere usati in modo intercambiabile?


Nel mio VS2005 in esecuzione su un processore a 32 bit, la dimensione predefinita di int è 4 byte.


Se vuoi scrivere codice portatile, considera l'utilizzo di #include <stdint.h>e poi i tipi che indicano la dimensione. Ad esempio uint32_t. Su una nuova piattaforma, devi solo assicurarti che stdint.h sia corretto per quella particolare piattaforma e che il tuo codice funzioni come previsto.
BitTickler

Risposte:


112

Dipende dall'implementazione.

Ad esempio, sotto Windows sono gli stessi, ma per esempio sui sistemi Alpha un long era di 64 bit mentre un int era di 32 bit. Questo articolo tratta le regole per il compilatore Intel C ++ su piattaforme variabili. Riassumere:

  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  

Penso che dovremmo considerare di combinare questa risposta (una risposta con un esempio) con alcuni dei dettagli di seguito relativi allo standard C ++. La bozza per C ++ 0x è su open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2798.pdf ed è contrassegnata in modo da poter vedere le differenze tra essa e l'ultima revisione.
Patrick Johnmeyer

Includere qualcosa nell'ordine relativo alle dimensioni dei tipi produce molte più informazioni rispetto all'enumerazione delle dimensioni per piattaforme diverse, come afferma @Kevin così bene. (-1vote)
xtofl

2
Alcuni compilatori hanno anche flag che ti permettono di modificare la dimensione predefinita di int e long, cioè forzarli a 8 o 16 ecc. Vedi la documentazione del compilatore per i dettagli.
Martin York

7
NB che queste sono le taglie lunghe
rogerdpack

1
Si prega di includere anche le dimensioni di int.
cegprakash

82

Le uniche garanzie che hai sono:

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

Vedi anche: È longgarantito che siano almeno 32 bit?


1
Hmm, questo non vale, se sizeof (short)> = sizeof (char) sappiamo solo che sizeof (short)> = 1 (non> = 2), che btw vale per tutti i tipi. Secondo questa dimensione di (qualsiasi tipo integrale)> = 1. Che è vero, ad esempio ricordo sizeof (int) == 1 sullo Z80, ma non esiste una garanzia più forte a lungo?
Andreas Magnusson

6
3.9.1.2 dello standard C ++ specifica che sizeof (long)> = sizeof (int)> = sizeof (short)> = sizeof (char) 5.3.3.1 dello standard C ++ specifica che sizeof (char), sizeof (unsigned char) e sizeof (carattere con segno) è uguale a 1. (cont ...)
KTC

4
(... cont) I valori massimo e minimo rappresentabili dai tipi integrali sono definiti come macro in <limits.h> (e quindi <climits>). L'allegato E dello standard C (1990), incluso come riferimento dallo standard C ++, specifica le grandezze minime di queste macro. (cont ...)
KTC

4
(... cont) e sono (2 ^ 15) -1, (2 ^ 15) -1, (2 ^ 31) -1, rispettivamente per short, int e long, che risulta essere il valore come pubblicato da Martin York nella sua risposta qui se CHAR_BIT è 8 (che è anche il suo valore minimo).
KTC

2
@ Giles: non è quello che ho detto sopra? sizeof (short) * CHAR_BITS> = 16. Plust alcune altre cose. :-)
Martin York

13

Quando si compila per x64, la differenza tra int e long è compresa tra 0 e 4 byte, a seconda del compilatore utilizzato.

GCC utilizza il modello LP64, il che significa che gli int sono a 32 bit ma i long sono a 64 bit in modalità a 64 bit.

MSVC ad esempio utilizza il modello LLP64, il che significa che sia int che long sono a 32 bit anche in modalità a 64 bit.


forse 0 byte? hmm
rogerdpack

12

La specifica C ++ stessa (vecchia versione ma abbastanza buona per questo) lo lascia aperto.

Sono disponibili quattro tipi di numeri interi con segno: " signed char", " short int", " int" e " long int". In questo elenco, ogni tipo fornisce almeno lo stesso spazio di archiviazione di quelli che lo precedono nell'elenco. Gli int semplici hanno la dimensione naturale suggerita dall'architettura dell'ambiente di esecuzione *;

[Nota a piè di pagina: cioè sufficientemente grande da contenere qualsiasi valore nell'intervallo di INT_MIN e INT_MAX, come definito nell'intestazione <climits>. --- fine nota]


7

Come sottolinea Kevin Haines, gli int hanno la dimensione naturale suggerita dall'ambiente di esecuzione, che deve rientrare in INT_MIN e INT_MAX.

Lo standard C89 afferma che UINT_MAXdovrebbe essere almeno 2 ^ 16-1, USHRT_MAX2 ^ 16-1 e ULONG_MAX2 ^ 32-1. Questo fa un conteggio dei bit di almeno 16 per short e int e 32 per long. Per char si afferma esplicitamente che dovrebbe avere almeno 8 bit ( CHAR_BIT). C ++ eredita queste regole per il file limits.h, quindi in C ++ abbiamo gli stessi requisiti fondamentali per quei valori. Tuttavia, non dovresti derivare da ciò che int è almeno 2 byte. Teoricamente, char, int e long potrebbero essere tutti 1 byte, nel qual caso CHAR_BITdeve essere almeno 32. Ricorda solo che "byte" è sempre la dimensione di un char, quindi se char è più grande, un byte non è solo 8 bit qualsiasi Di Più.


Non pensavo che byteesistesse un tipo di dati in C ++. Non è vero? Se lo fa, e a bytepuò avere dimensioni diverse da 8 bit, è semplicemente stupido. Perché lo chiamerebbero byte a meno che non sia assolutamente necessariamente 8 bit?
Alderath

6

Dipende dal tuo compilatore. Hai la certezza che un long sarà grande almeno quanto un int, ma non sei sicuro che lo sarà più.


5

Per la maggior parte, il numero di byte e l'intervallo di valori è determinato dall'architettura della CPU non da C ++. Tuttavia, C ++ stabilisce i requisiti minimi, che litb ha spiegato correttamente e Martin York ha commesso solo alcuni errori.

Il motivo per cui non puoi usare int e long in modo intercambiabile è perché non sono sempre della stessa lunghezza. C è stato inventato su un PDP-11 dove un byte aveva 8 bit, int era due byte e poteva essere gestito direttamente dalle istruzioni hardware. Poiché i programmatori C spesso avevano bisogno di operazioni aritmetiche a quattro byte, fu inventato long ed era di quattro byte, gestito dalle funzioni di libreria. Altre macchine avevano specifiche diverse. Lo standard C imponeva alcuni requisiti minimi.


5

Affidarsi all'implementazione del fornitore del compilatore di dimensioni di tipo primitivo tornerà a perseguitarti se mai compili il tuo codice su un'altra architettura di macchina, sistema operativo o compilatore di un altro fornitore.

La maggior parte dei fornitori di compilatori fornisce un file di intestazione che definisce i tipi primitivi con dimensioni di tipo esplicite. Questi tipi primitivi dovrebbero essere usati ogni volta che il codice può essere potenzialmente portato su un altro compilatore (leggilo SEMPRE in OGNI istanza). Ad esempio, la maggior parte dei compilatori UNIX ha int8_t uint8_t int16_t int32_t uint32_t. Microsoft ha INT8 UINT8 INT16 UINT16 INT32 UINT32. Preferisco Borland / CodeGear's int8 uint8 int16 uint16 int32 uint32. Questi nomi forniscono anche un piccolo promemoria della dimensione / intervallo del valore previsto.

Per anni ho usato i nomi dei tipi primitivi espliciti di Borland e #includeil seguente file di intestazione C / C ++ (primitive.h) che ha lo scopo di definire i tipi primitivi espliciti con questi nomi per qualsiasi compilatore C / C ++ (questo file di intestazione potrebbe non coprire ogni compilatore ma copre diversi compilatori che ho usato su Windows, UNIX e Linux, inoltre non definisce (ancora) i tipi a 64 bit).

#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

C99 impone che typdef che assomigliano a int32_t, uint64_t, ecc siano definiti dal compilatore e abbiano esattamente tanti bit quanti ne suggerisce il nome. La maggior parte dei compilatori C ++ (incluso g ++) ti consentirà di utilizzare queste costanti nel codice C ++.
rmeador

5

Lo standard C ++ lo dice in questo modo:

3.9.1, §2:

Esistono cinque tipi di interi con segno: "signed char", "short int", "int", "long int" e "long long int". In questo elenco, ogni tipo fornisce almeno lo stesso spazio di archiviazione di quelli che lo precedono nell'elenco. Gli int semplici hanno la dimensione naturale suggerita dall'architettura dell'ambiente di esecuzione (44); gli altri tipi di interi con segno vengono forniti per soddisfare esigenze speciali.

(44) cioè, sufficientemente grande da contenere qualsiasi valore nell'intervallo di INT_MIN e INT_MAX, come definito nell'intestazione <climits> .

La conclusione: dipende dall'architettura su cui stai lavorando. Ogni altra ipotesi è falsa.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.