Cosa indica lo standard C ++ della dimensione di int, long type?

Sto cercando informazioni dettagliate sulla dimensione dei tipi base di C ++. So che dipende dall’architettura (16 bit, 32 bit, 64 bit) e dal compilatore.

Ma ci sono degli standard per il C ++?

Sto usando Visual Studio 2008 su un’architettura a 32 bit. Ecco cosa ottengo:

char : 1 byte short : 2 bytes int : 4 bytes long : 4 bytes float : 4 bytes double: 8 bytes 

Ho cercato di trovare, senza molto successo, informazioni attendibili affermando le dimensioni di char , short , int , long , double , float (e altri tipi a cui non pensavo) in architetture e compilatori diversi.

Lo standard C ++ non specifica la dimensione dei tipi interi in byte, ma specifica gli intervalli minimi che devono essere in grado di contenere. È ansible dedurre la dimensione minima in bit dall’intervallo richiesto. È ansible dedurre la dimensione minima in byte da quella e il valore della macro CHAR_BIT che definisce il numero di bit in un byte (in tutte le piattaforms tranne le più oscure è 8 e non può essere inferiore a 8).

Un ulteriore vincolo per char è che la sua dimensione è sempre 1 byte, o bit CHAR_BIT (da cui il nome).

Gli intervalli minimi richiesti dallo standard (pagina 22) sono:

e intervalli di tipo dati su MSDN :

  1. signed char : da -127 a 127 (nota, non da -128 a 127, questo ospita le piattaforms di complemento d’oro e di segno-e-magnitudine)
  2. unsigned char : da 0 a 255
  3. char “plain”: stesso intervallo del signed char o del unsigned char , definito dall’implementazione
  4. signed short : da -32767 a 32767
  5. unsigned short : da 0 a 65535
  6. signed int : da -32767 a 32767
  7. unsigned int : da 0 a 65535
  8. signed long : -2147483647 a 2147483647
  9. unsigned long : da 0 a 4294967295
  10. signed long long : -9223372036854775807 a 9223372036854775807
  11. unsigned long long : da 0 a 18446744073709551615

Un’implementazione C ++ (o C) può definire la dimensione di un tipo in byte sizeof(type) a qualsiasi valore, purché

  1. l’espressione sizeof(type) * CHAR_BIT un numero di bit abbastanza alto da contenere gli intervalli richiesti e
  2. l’ordinamento di tipo è ancora valido (es. sizeof(int) < = sizeof(long) ).

Gli intervalli effettivi specifici per l'implementazione possono essere trovati nell'intestazione in C, o in C ++ (o anche meglio, nel std::numeric_limits nell'intestazione ).

Ad esempio, questo è il modo in cui troverai l'intervallo massimo per int :

C:

 #include  const int min_int = INT_MIN; const int max_int = INT_MAX; 

C ++ :

 #include  const int min_int = std::numeric_limits::min(); const int max_int = std::numeric_limits::max(); 

Per i sistemi a 32 bit, lo standard “de facto” è ILP32, ovvero int , long e pointer sono tutte le quantità a 32 bit.

Per i sistemi a 64 bit, lo standard ‘de facto’ primario di Unix è LP64 – long e il puntatore è a 64 bit (ma int è a 32 bit). Lo standard Windows 64-bit è LLP64 – long long e pointer a 64-bit (ma long e int sono entrambi a 32-bit).

Un tempo, alcuni sistemi Unix utilizzavano un’organizzazione ILP64.

Nessuno di questi standard de facto è legiferato dallo standard C (ISO / IEC 9899: 1999), ma tutti sono autorizzati da questo.

E, per definizione, sizeof(char) è 1 , nonostante il test nello script di configurazione Perl.

Si noti che c’erano macchine (Crays) dove CHAR_BIT era molto più grande di 8. Ciò significava, IIRC, che sizeof(int) era anche 1, perché sia char che int erano a 32 bit.

In pratica non esiste una cosa del genere. Spesso puoi aspettarti che std::size_t rappresenti la dimensione intera nativa non firmata sull’architettura corrente. cioè 16-bit, 32-bit o 64-bit ma non è sempre il caso come indicato nei commenti a questa risposta.

Per quanto riguarda tutti gli altri tipi built-in, dipende molto dal compilatore. Ecco due estratti tratti dalla bozza di lavoro corrente dell’ultimo standard C ++:

Esistono cinque tipi di interi con segno standard: signed char, short int, int, long int e long long int. In questo elenco, ciascun tipo fornisce almeno lo stesso spazio di archiviazione di quelli che lo precedono nell’elenco.

Per ciascuno dei tipi di interi con segno standard esiste un corrispondente (non diverso) standard di tipo intero senza segno: unsigned char, unsigned short int, unsigned int, unsigned long int e unsigned long long int, ognuno dei quali occupa la stessa quantità di archiviazione e ha gli stessi requisiti di allineamento.

Se lo desideri puoi staticamente (in fase di compilazione) asserire la dimensione di questi tipi fondamentali. Allerta le persone a pensare al porting del tuo codice se cambia la dimensione delle ipotesi.

C’è lo standard

Lo standard C90 lo richiede

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

Lo standard C99 lo richiede

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

Ecco le specifiche C99 . Pagina 22 dettagli dimensioni di diversi tipi di integrale.

Ecco le dimensioni int type (bit) per le piattaforms Windows:

 Type C99 Minimum Windows 32bit char 8 8 short 16 16 int 16 32 long 32 32 long long 64 64 

Se si è interessati alla portabilità o si desidera che il nome del tipo rifletta la dimensione, è ansible consultare l'intestazione , dove sono disponibili le seguenti macro:

 int8_t int16_t int32_t int64_t 

int8_t è garantito per essere 8 bit, e int16_t è garantito per essere 16 bit, ecc.

Se sono necessari tipi di dimensioni fisse, utilizzare tipi come uint32_t (numero intero senza segno a 32 bit) definito in stdint.h . Sono specificati in C99 .

Aggiornato: C ++ 11 ha portato i tipi di TR1 ufficialmente nello standard:

  • lungo int lungo
  • unsigned long long int

E i tipi “dimensionati” da

  • int8_t
  • int16_t
  • int32_t
  • int64_t
  • (e le controparti non firmate).

Inoltre ottieni:

  • int_least8_t
  • int_least16_t
  • int_least32_t
  • int_least64_t
  • Più le controparti non firmate.

Questi tipi rappresentano i tipi interi più piccoli con almeno il numero specificato di bit. Allo stesso modo ci sono i tipi interi “più veloci” con almeno il numero specificato di bit:

  • int_fast8_t
  • int_fast16_t
  • int_fast32_t
  • int_fast64_t
  • Inoltre le versioni senza firma.

Cosa significa “veloce”, se non altro, dipende dall’implementazione. Non è necessario che sia il più veloce a tutti gli effetti.

Lo standard C ++ 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, ciascun tipo fornisce almeno lo stesso spazio di archiviazione di quelli che lo precedono nell’elenco. I plain ints hanno le dimensioni naturali suggerite dall’architettura dell’ambiente di esecuzione (44); gli altri tipi di interi con segno sono forniti per soddisfare esigenze particolari.

(44) cioè, abbastanza grande da contenere qualsiasi valore nell’intervallo di INT_MIN e INT_MAX, come definito nell’intestazione .

La conclusione: dipende da quale architettura stai lavorando. Ogni altra ipotesi è falsa.

No, non esiste uno standard per le dimensioni del testo. Lo standard richiede solo che:

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

La cosa migliore che puoi fare se vuoi le variabili di dimensioni fisse è usare macro come questa:

 #ifdef SYSTEM_X #define WORD int #else #define WORD long int #endif 

Quindi puoi usare WORD per definire le tue variabili. Non è che mi piaccia, ma è il modo più portabile .

Siamo autorizzati a definire un sinonimo per il tipo in modo da poter creare il nostro “standard”.

Su una macchina in cui sizeof (int) == 4, possiamo definire:

 typedef int int32; int32 i; int32 j; ... 

Quindi, quando trasferiamo il codice su una macchina diversa, dove in realtà la dimensione di long int è 4, possiamo semplicemente ridefinire la singola occorrenza di int.

 typedef long int int32; int32 i; int32 j; ... 

Per i numeri in virgola mobile esiste uno standard (IEEE754) : i float sono a 32 bit e i doppi 64. Si tratta di uno standard hardware, non di uno standard C ++, quindi i compilatori potrebbero teoricamente definire float e double a qualche altra dimensione, ma in pratica I ‘ Non ho mai visto un’architettura che usasse qualcosa di diverso.

Esiste uno standard ed è specificato nei vari documenti standard (ISO, ANSI e quant’altro).

Wikipedia ha una grande pagina che spiega i vari tipi e il massimo che possono contenere: Numero intero in Informatica.

Tuttavia, anche con un compilatore C ++ standard è ansible scoprire in modo relativamente semplice utilizzando il seguente frammento di codice:

 #include  #include  int main() { // Change the template parameter to the various different types. std::cout < < std::numeric_limits::max() < < std::endl; } 

La documentazione di std :: numeric_limits è disponibile su Roguewave . Include una pletora di altri comandi che puoi chiamare per scoprire i vari limiti. Può essere utilizzato con qualsiasi tipo arbitrario che trasmetta le dimensioni, ad esempio std :: streamsize.

La risposta di John contiene la descrizione migliore, come è garantito. A prescindere dalla piattaforma su cui ti trovi, c'è un'altra buona pagina che fornisce maggiori dettagli sul numero di bit che ogni tipo DEVE contenere: tipi int , che sono definiti nello standard.

Spero che aiuti!

1) Tabella N1 nell’articolo ” I problemi dimenticati dello sviluppo di programmi a 64 bit ”

2) ” Modello dati ”

Puoi usare:

 cout < < "size of datatype = " << sizeof(datatype) << endl; 

datatype = int , long int ecc. Sarai in grado di vedere la dimensione per qualsiasi tipo di dati digitato.

Quando si tratta di tipi integrati per architetture diverse e compilatori diversi, basta eseguire il codice seguente sulla propria architettura con il compilatore per vedere cosa emette. Qui sotto mostra la mia uscita Ubuntu 13.04 (Raring Ringtail) a 64 bit g ++ 4.7.3. Inoltre, si prega di notare cosa è stato risposto di seguito che è il motivo per cui l’output è ordinato in quanto tale:

“Esistono cinque tipi di interi con segno standard: 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.”

 #include  int main ( int argc, char * argv[] ) { std::cout< < "size of char: " << sizeof (char) << std::endl; std::cout<< "size of short: " << sizeof (short) << std::endl; std::cout<< "size of int: " << sizeof (int) << std::endl; std::cout<< "size of long: " << sizeof (long) << std::endl; std::cout<< "size of long long: " << sizeof (long long) << std::endl; std::cout<< "size of float: " << sizeof (float) << std::endl; std::cout<< "size of double: " << sizeof (double) << std::endl; std::cout<< "size of pointer: " << sizeof (int *) << std::endl; } size of char: 1 size of short: 2 size of int: 4 size of long: 8 size of long long: 8 size of float: 4 size of double: 8 size of pointer: 8 

Come accennato, la dimensione dovrebbe riflettere l’architettura corrente. Potresti fare un picco in limits.h se vuoi vedere come il tuo compilatore sta gestendo le cose.

Come altri hanno risposto, gli “standard” lasciano la maggior parte dei dettagli come “implementazione definita” e solo lo stato che tipo “char” ha leat “char_bis” wide, e che “char < = short <= int <= long < = long long "(float e double sono praticamente coerenti con gli standard IEEE in virgola mobile, e long double è in genere uguale a double), ma potrebbe essere maggiore su implementazioni più recenti).

Parte dei motivi per cui non si hanno valori molto specifici e precisi è perché linguaggi come C / C ++ sono stati progettati per essere portabili su un gran numero di piattaforms hardware – Compresi i sistemi informatici in cui la dimensione della parola “char” può essere di 4 bit o 7-bit, o anche qualche valore diverso dai computer “8- / 16- / 32- / 64-bit” a cui è esposto l’utente medio del computer di casa. (Dimensione della parola qui significa il numero di bit su cui il sistema normalmente opera – Anche in questo caso, non sempre gli 8 bit come gli utenti di computer domestici possono aspettarsi.)

Se hai davvero bisogno di un object (nel senso di una serie di bit che rappresentano un valore integrale) di un numero specifico di bit, la maggior parte dei compilatori ha un metodo per specificarlo; Ma in genere non è portabile, nemmeno tra i compilatori realizzati dalla società ame, ma per piattaforms diverse. Alcuni standard e pratiche (specialmente limits.h e simili) sono abbastanza comuni che la maggior parte dei compilatori avrà il supporto per determinare il tipo più adatto per uno specifico intervallo di valori, ma non il numero di bit utilizzati. (Ovvero, se sai che è necessario mantenere valori compresi tra 0 e 127, puoi determinare che il tuo compilatore supporta un tipo “int8” di 8 bit che sarà abbastanza grande da contenere l’intera gamma desiderata, ma non qualcosa come un tipo “int7” che sarebbe una corrispondenza esatta per 7 bit.)

Nota: molti pacchetti Un * x source usano lo script “./configure” che sonderà le capacità del compilatore / sistema e produrrà un Makefile e config.h adatti. Potresti esaminare alcuni di questi script per vedere come funzionano e come sondare le capacità del comiler / sistema e seguire la loro guida.

Se sei interessato a una soluzione C ++ pura, ho utilizzato template e solo codice standard C ++ per definire i tipi al momento della compilazione in base alla dimensione del loro bit. Ciò rende la soluzione portatile attraverso i compilatori.

L’idea alla base è molto semplice: creare una lista contenente i tipi char, int, short, long, long long (versioni firmate e non firmate) e scansionare l’elenco e con l’uso del template numeric_limits selezionare il tipo con una determinata dimensione.

Includendo questa intestazione hai 8 stdtype :: int8, stdtype :: int16, stdtype :: int32, stdtype :: int64, stdtype :: uint8, stdtype :: uint16, stdtype :: uint32, stdtype :: uint64.

Se non è ansible rappresentare alcun tipo, verrà valutato anche stdtype :: null_type dichiarato in tale intestazione.

IL CODICE SUCCESSIVO VIENE RICEVUTO SENZA GARANZIA, PER FAVORE VERIFICARLA.
SONO NUOVO A METAPROGRAMMING, SONO LIBERO DI MODIFICARE E CORREGGERE QUESTO CODICE.
Testato con DevC ++ (quindi una versione gcc circa 3.5)

 #include  namespace stdtype { using namespace std; /* * THIS IS THE CLASS USED TO SEMANTICALLY SPECIFY A NULL TYPE. * YOU CAN USE WHATEVER YOU WANT AND EVEN DRIVE A COMPILE ERROR IF IT IS * DECLARED/USED. * * PLEASE NOTE that C++ std define sizeof of an empty class to be 1. */ class null_type{}; /* * Template for creating lists of types * * T is type to hold * S is the next type_list type * * Example: * Creating a list with type int and char: * typedef type_list > test; * test::value //int * test::next::value //char */ template  struct type_list { typedef T value; typedef S next; }; /* * Declaration of template struct for selecting a type from the list */ template  struct select_type; /* * Find a type with specified "b" bit in list "list" * * */ template  struct find_type { private: //Handy name for the type at the head of the list typedef typename list::value cur_type; //Number of bits of the type at the head //CHANGE THIS (compile time) exp TO USE ANOTHER TYPE LEN COMPUTING enum {cur_type_bits = numeric_limits::digits}; public: //Select the type at the head if b == cur_type_bits else //select_type call find_type with list::next typedef typename select_type::type type; }; /* * This is the specialization for empty list, return the null_type * OVVERRIDE this struct to ADD CUSTOM BEHAVIOR for the TYPE NOT FOUND case * (ie search for type with 17 bits on common archs) */ template  struct find_type { typedef null_type type; }; /* * Primary template for selecting the type at the head of the list if * it matches the requested bits (b == ctl) * * If b == ctl the partial specified templated is evaluated so here we have * b != ctl. We call find_type on the next element of the list */ template  struct select_type { typedef typename find_type::type type; }; /* * This partial specified templated is used to select top type of a list * it is called by find_type with the list of value (consumed at each call) * the bits requested (b) and the current type (top type) length in bits * * We specialice the b == ctl case */ template  struct select_type { typedef typename list::value type; }; /* * These are the types list, to avoid possible ambiguity (some weird archs) * we kept signed and unsigned separated */ #define UNSIGNED_TYPES type_list > > > > #define SIGNED_TYPES type_list > > > > /* * These are acutally typedef used in programs. * * Nomenclature is [u]intN where u if present means unsigned, N is the * number of bits in the integer * * find_type is used simply by giving first a type_list then the number of * bits to search for. * * NB. Each type in the type list must had specified the template * numeric_limits as it is used to compute the type len in (binary) digit. */ typedef find_type::type uint8; typedef find_type::type uint16; typedef find_type::type uint32; typedef find_type::type uint64; typedef find_type::type int8; typedef find_type::type int16; typedef find_type::type int32; typedef find_type::type int64; } 
 unsigned char bits = sizeof(X) < < 3; 

dove X è un char , int , long ecc. ti darà la dimensione di X in bit.

Da Alex B Lo standard C ++ non specifica la dimensione dei tipi interi in byte, ma specifica gli intervalli minimi che devono essere in grado di contenere. È ansible dedurre la dimensione minima in bit dall’intervallo richiesto. È ansible dedurre la dimensione minima in byte da quella e il valore della macro CHAR_BIT che definisce il numero di bit in un byte (in tutte le piattaforms tranne le più oscure è 8 e non può essere inferiore a 8).

Un ulteriore vincolo per char è che la sua dimensione è sempre 1 byte, o bit CHAR_BIT (da cui il nome).

Gli intervalli minimi richiesti dallo standard (pagina 22) sono:

e intervalli di tipo dati su MSDN:

char firmato: da -127 a 127 (nota, non da -128 a 127, questo accomoda le piattaforms a complemento d’oro) char senza segno: da 0 a 255 “plain” char: da -127 a 127 o da 0 a 255 (dipende dalla firma firmata predefinita) firmato breve: da -32767 a 32767 senza segno corto: da 0 a 65535 con segno int: da -32767 a 32767 senza segno: da 0 a 65535 con segno lungo: -2147483647 a 2147483647 non firmato lungo: da 0 a 4294967295 lungo lungo: -9223372036854775807 a 9223372036854775807 non firmato lungo lungo: Da 0 a 18446744073709551615 Un’implementazione C ++ (o C) può definire la dimensione di un tipo in byte sizeof (tipo) su qualsiasi valore, purché

l’espressione sizeof (type) * CHAR_BIT valuta il numero di bit sufficiente per contenere gli intervalli richiesti e l’ordinamento di tipo è ancora valido (ad esempio sizeof (int) < = sizeof (long)). Gli intervalli effettivi specifici per l'implementazione possono essere trovati nell'intestazione in C, o in C ++ (o anche meglio, nel codice std :: numeric_limits nell'intestazione).

Ad esempio, questo è il modo in cui troverai l’intervallo massimo per int:

C:

 #include  const int min_int = INT_MIN; const int max_int = INT_MAX; 

C ++:

 #include  const int min_int = std::numeric_limits::min(); const int max_int = std::numeric_limits::max(); 

Questo è corretto, tuttavia, hai anche ragione nel dire che: char: 1 byte breve: 2 byte int: 4 byte lungo: 4 byte float: 4 byte double: 8 byte

Poiché le architetture a 32 bit sono ancora quelle predefinite e più utilizzate, e hanno mantenuto queste dimensioni standard dai primi di 32 giorni in cui la memoria era meno disponibile, e per compatibilità e standardizzazione al contrario è rimasta la stessa. Anche i sistemi a 64 bit tendono a usarli e hanno estensioni / modifiche. Si prega di fare riferimento a questo per ulteriori informazioni:

http://en.cppreference.com/w/cpp/language/types

Ho notato che tutte le altre risposte qui si sono concentrate quasi esclusivamente sui tipi interi, mentre l’interrogante ha anche chiesto dei punti fluttuanti.

Non credo che lo standard C ++ lo richieda, ma i compilatori per le piattaforms più comuni in questi giorni seguono generalmente lo standard IEEE754 per i loro numeri in virgola mobile. Questo standard specifica quattro tipi di binario in virgola mobile (così come alcuni formati BCD, che non ho mai visto il supporto per i compilatori C ++):

  • Mezza precisione (binario16) – significato 11 bit e intervallo esponenziale da -14 a 15
  • Precisione singola (binario32) – significato a 24 bit e intervallo di esponente da -126 a 127
  • Doppia precisione (binary64) – significato di 53 bit e intervallo di esponente da -1022 a 1023
  • Precisione quadrupla (binario128) – significato di 113 bit e intervallo di esponente da -16382 a 16383

Come funziona questa mappa sui tipi di C ++, quindi? Generalmente il float usa una precisione singola; quindi, sizeof(float) = 4 . Then double uses double precision (I believe that’s the source of the name double ), and long double may be either double or quadruple precision (it’s quadruple on my system, but on 32-bit systems it may be double). I don’t know of any compilers that offer half precision floating-points.

In summary, this is the usual:

  • sizeof(float) = 4
  • sizeof(double) = 8
  • sizeof(long double) = 8 or 16

As you mentioned – it largely depends upon the compiler and the platform. For this, check the ANSI standard, http://home.att.net/~jackklein/c/inttypes.html

Here is the one for the Microsoft compiler: Data Type Ranges .

You can use variables provided by libraries such as OpenGL , Qt , etc.

For example, Qt provides qint8 (guaranteed to be 8-bit on all platforms supported by Qt), qint16, qint32, qint64, quint8, quint16, quint32, quint64, etc.

On a 64-bit machine:

 int: 4 long: 8 long long: 8 void*: 8 size_t: 8 

There are four types of integers based on size:

  • short integer: 2 byte
  • long integer: 4 byte
  • long long integer: 8 byte
  • integer: depends upon the compiler (16 bit, 32 bit, or 64 bit)