Qual è lo standard C ++ che indica la dimensione di int, long type?


696

Sto cercando informazioni dettagliate sulla dimensione dei tipi di base 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, di informazioni affidabili indicando le dimensioni di char, short, int, long, double, float(e di altri tipi non pensavo di) sotto diverse architetture e compilatori.


18
@thyrgle non è per scelta ... ci sono così tante architetture da supportare che deve essere flessibile.
Cracovia


4
Perché non rimuovono tutti i tipi vaghi e li standardizzano per definire determinati tipi di lunghezza dei bit, ad esempio int32_t, uint32_t, int64_t ecc.
Developerbmw,

5
@thyrgle In realtà è abbastanza difficile standardizzare qualcosa del genere. A differenza di Java, dove queste cose sono costanti a causa del modo in cui funziona la JVM, C / C ++ essenzialmente deve attenersi al sistema su cui sono state eseguite senza alcun livello di astrazione fantasioso (almeno non tanto quanto con Java) in- fra. Se la dimensione dell'int è quella che si può usare int16_t, int32_te int64_t(è necessario iostreamincluderla se ricordo bene). La cosa bella di questo è che int64_t non dovrebbe avere problemi su un sistema a 32 bit (questo influenzerà le prestazioni).
rbaleksandar,

5
@rbaleksandar In realtà sono definiti in <cstdint>, no <iostream>.
Justin Time - Ripristina Monica il

Risposte:


685

Lo standard C ++ non specifica la dimensione dei tipi integrali in byte, ma specifica gli intervalli minimi che devono essere in grado di contenere. È possibile dedurre la dimensione minima in bit dall'intervallo richiesto. È possibile dedurre la dimensione minima in byte da quella e il valore della CHAR_BITmacro che definisce il numero di bit in un byte . In tutte le piattaforme tranne quelle più oscure è 8 e non può essere inferiore a 8. Questo perché deve essere abbastanza grande da contenere "le unità di codice a otto bit del modulo di codifica Unicode UTF-8".

Un ulteriore vincolo charè che la sua dimensione è sempre 1 byte o CHAR_BITbit (da cui il nome). Questo è dichiarato esplicitamente nello standard.

Lo standard C è un riferimento normativo per lo standard C ++, quindi anche se non specifica esplicitamente questi requisiti, C ++ richiede gli intervalli minimi richiesti dallo standard C (pagina 22), che sono gli stessi di quelli dei range di tipi di dati su MSDN :

  1. signed char: Da -127 a 127 (nota, non da -128 a 127; questo supporta piattaforme complemento a 1 e segno e magnitudine)
  2. unsigned char: Da 0 a 255
  3. "plain" char: stesso intervallo di signed charo 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: Da -2147483647 a 2147483647
  9. unsigned long: Da 0 a 4294967295
  10. signed long long: Da -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)per qualsiasi valore, purché

  1. l'espressione sizeof(type) * CHAR_BITrestituisce un numero di bit sufficientemente elevato da contenere intervalli richiesti e
  2. l'ordinamento del tipo è ancora valido (ad es sizeof(int) <= sizeof(long).).

Mettendo tutto insieme, siamo garantiti che:

  • char, signed chare unsigned charsono almeno 8 bit
  • signed short, unsigned short, signed int, E unsigned intsono almeno 16 bit
  • signed longe unsigned longsono almeno 32 bit
  • signed long longe unsigned long longsono almeno 64 bit

Non viene fornita alcuna garanzia circa le dimensioni floato doubletranne che doublefornisce almeno la stessa precisione float.

Le gamme di attuazione specifiche effettivi possono essere trovati in <limits.h>intestazione in C o <climits>in C ++ (o meglio ancora, basati su modelli std::numeric_limitsin <limits>intestazione).

Ad esempio, ecco come troverai la portata massima per int:

C:

#include <limits.h>
const int min_int = INT_MIN;
const int max_int = INT_MAX;

C ++ :

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

49
Piuttosto, lo standard C ++ usa la parola byte per significare "1 char", e non il solito significato.
Ben Voigt,

4
@Programmer Leggi la risposta (punto 1 nota tra parentesi) o la dicitura dello standard effettivo (collegata nella risposta). Lo standard C ospita architetture di complementi di 1, che hanno una rappresentazione diversa dal complemento di 2 più diffuso. Gli intervalli minimi garantiti differiranno quasi sempre dagli intervalli effettivi forniti da un'implementazione.
Alex B,

9
@Alex B non hai menzionato nulla del doppio nella tua risposta. Puoi aggiornare la tua risposta per variabili in virgola mobile?
Cool_Coder

3
@Cool_Coder: La virgola mobile è un intero bollitore aggiuntivo di pesce, che raddoppia facilmente le dimensioni dei pali.
Deduplicatore,

3
@Mooing Duck: "tutte le versioni di C ++ richiedevano 256 valori distinti [per i tipi di caratteri firmati]" No, questo non era vero fino a quando non veniva corretto nelle specifiche C ++ più recenti. Le specifiche precedenti consentivano ai tipi di caratteri firmati di avere modelli di bit che non si associano a un numero, quindi mancava il requisito che ci fossero 256 valori distinti. "Per i tipi di carattere senza segno, tutti i possibili pattern di bit della rappresentazione del valore rappresentano numeri. Questi requisiti non valgono per altri tipi."
Adrian McCarthy,

241

Per i sistemi a 32 bit, lo standard 'de facto' è ILP32 - che è, int, longe puntatore sono tutte le quantità a 32 bit.

Per i sistemi a 64 bit, lo standard 'de facto' principale di Unix è LP64 - longe il puntatore è a 64 bit (ma intè a 32 bit). Lo standard di Windows a 64 bit è LLP64 - long longe il puntatore è a 64 bit (ma longe intsono entrambi a 32 bit).

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

Nessuna di queste norme di fatto è legiferata dalla norma C (ISO / IEC 9899: 1999), ma tutte sono permesse da essa.

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

Si noti che c'erano macchine (Crays) in cui CHAR_BITera molto più grande di 8. Ciò significava, IIRC, che sizeof(int)era anche 1, perché entrambi chare interano a 32 bit.


73
+1 per indicare come stanno le cose nei casi che contano di più, piuttosto che come sono le cose in teoria. Se vuoi 32 bit usa int, se vuoi 64 bit usa molto a lungo. Se si desidera utilizzare nativo size_t. Evita il "semplice" lungo perché varia. Questo dovrebbe funzionare per la maggior parte delle applicazioni.
Eloff

37
+1 per la risposta. @Eloff: al contrario ... se vuoi un uso a 32 bit [u]int32_to simile, se vuoi un uso a 64 bit [u]int64_t... se non hai un header per loro, scaricalo o creane uno, preferibilmente con la selezione del tempo di compilazione di tali tipi o asserzioni statiche per verificare le dimensioni. pubs.opengroup.org/onlinepubs/009695299/basedefs/stdint.h.html Se le dimensioni precise non sono così importanti e ti importa solo che siano almeno così grandi, i tuoi consigli valgono per le piattaforme PC / server moderne più comuni.
Tony Delroy,

8
Nota che non sono solo le vecchie macchine per pasticciere che hanno CHAR_BIT> 8. ad esempio, i DSP hanno spesso CHAR_BIT di 16 o 32. (vedi ad esempio questi )
nn

2
@nos: grazie per il link. È molto utile identificare sistemi moderni e attuali per i casi dispari. Per curiosità, qual è il codice impostato su quelle macchine? Se il set di codici è UTF-16, allora 0xFFFF non è un carattere valido e se il set di codici è un set di codici ISO 8859-x, quindi di nuovo 0xFFFF non è un carattere valido (i codici di caratteri da 0x00 a 0xFF sono validi). Non sono ancora convinto che ci sia un problema nel rilevare EOF, ma c'è sicuramente spazio per cautela e probabilmente per scrivere e usare una funzione int get_char(FILE *fp, char *c)che restituisce EOF o 0 e imposta *c.
Jonathan Leffler,

2
@joelw: C11 richiede che, dato che uint32_t x=1,y=2;il valore di x-ydeve essere 4294967295 su piattaforme in cui "int" è 32 bit o inferiore, e -1 su piattaforme in cui "int" è 33 bit o maggiore. Inoltre, richiede che x*ydebba essere valutato usando l'aritmetica modulare per tutti i valori di xey se "int" è 32 bit o inferiore, e l'aritmetica convenzionale se 65 bit o maggiore, ma non impone alcun requisito su ciò che può accadere con valori elevati di xey se "int" è compreso tra 33 e 64 bit.
supercat,

88

In pratica non esiste nulla del genere. Spesso ci si può aspettare std::size_tdi rappresentare la dimensione intera nativa senza segno sull'architettura corrente. vale a dire 16 bit, 32 bit o 64 bit, ma non è sempre il caso, come sottolineato nei commenti a questa risposta.

Per quanto riguarda tutti gli altri tipi predefiniti, dipende davvero dal compilatore. Ecco due estratti tratti dall'attuale bozza di lavoro dell'ultimo standard C ++:

Esistono cinque tipi di numeri interi con segno standard: carattere con segno, int breve, 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.

Per ciascuno dei tipi di numeri interi con segno standard, esiste un tipo di numero intero senza segno standard corrispondente (ma diverso): carattere senza segno, valore senza segno int, valore senza segno, valore con tempo lungo e valore con tempo lungo int, ognuno dei quali occupa la stessa quantità di archiviazione e ha gli stessi requisiti di allineamento.

Se lo desideri, puoi affermare staticamente (tempo di compilazione) la dimensione di questi tipi fondamentali. Avviserà le persone di pensare al porting del codice se la dimensione dei presupposti cambia.


7
buon post. un'altra cosa che è richiesta è la seguente dimensione minima di bit (documentata in c89 / c99 insieme a limits.h e rilevata da c ++): char> = 8, short e int> = 16, long> = 32.
Johannes Schaub -

1
Inoltre, su una piattaforma AVR a 8 bit size_t non sarà 8 bit, ma 16, poiché il puntatore e le dimensioni int sono 16 bit. Pertanto, la dimensione dei dati nativi del processore non è correlata a size_t.
Robotbugs,

80

C'è 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 integrali.

Ecco le dimensioni del tipo int (bit) per le piattaforme Windows:

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

Se sei interessato alla portabilità o desideri che il nome del tipo rifletta la dimensione, puoi guardare l'intestazione <inttypes.h>, dove sono disponibili le seguenti macro:

int8_t
int16_t
int32_t
int64_t

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


8
Piccolo nitpick: dove dice lo standard sizeof(long) < sizeof(long long)rispetto al simmetrico sizeof(long) <= sizeof(long long)?
Jonathan Leffler,

2
@JonathonLeffler - vedi C99 5.2.4.2.1 - Dimensioni dei tipi interi. minsizeof (int) == 16 bit, minsizeof (long) == 32-bit, minsizeof (long long) == 64-bit. Quindi penso che tu abbia ragione su <= poiché non viene specificato maxsizeof (tipo).
Jesse Chisholm,

Allo stesso modo sizeof (float) <= sizeof (double) <= sizeof (double double). Secondo C99 7.12, paragrafo 2.
Jesse Chisholm,

38

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


10
Sono specificati ma non richiesti.
dreamlax,

2
@dreamlax Quali piattaforme non lo includono?
Levi Morrison,

3
@LeviMorrison: qualsiasi piattaforma che non li ha nella forma richiesta. Una piattaforma che ha CHAR_BIT == 16, per esempio, non avrà int8_t. Qualsiasi piattaforma che non utilizza il complemento a due non ne avrà nessuno (poiché lo standard richiede il complemento a due).
DevSolar,

36

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

  • long long int
  • unsigned long long int

E i tipi "dimensionati" da <cstdint>

  • 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
  • Inoltre 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 non firmate.

Cosa significa "veloce" dipende dall'implementazione. Non è nemmeno il più veloce per tutti gli scopi.


Questo fa parte dello standard C ++ 11 ora.
Jaan,

2
"veloce" significa semplicemente adattato all'architettura hardware. Se i registri sono a 16 bit, int_fast8_t è un valore a 16 bit. Se i registri sono a 32 bit, int_fast8_t e int_fast16_t sono entrambi valori a 32 bit. ecc Vedere C99 sezione 7.18.1.3 paragrafo 2.
Jesse Chisholm

19

Lo standard C ++ lo dice così:

3.9.1, §2:

Esistono cinque tipi interi con segno: "firmato 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 ints semplici hanno le dimensioni naturali suggerite dall'architettura dell'ambiente di esecuzione (44); gli altri tipi interi firmati vengono forniti per soddisfare esigenze speciali.

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

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


12

No, non esiste uno standard per le dimensioni dei tipi. Lo standard richiede solo che:

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

La cosa migliore che puoi fare se vuoi 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ù portatile .


4
Il problema è che WORD si diffonde attorno al programma in aree che non dipendono veramente da una dimensione fissa (guarda un codice di Windows). Come ho scoperto quando si passa da un sistema da 16 bit a 32 bit, si ottiene lo stesso problema che WORD doveva risolvere.
lilburne,

@liburne Naturalmente dovresti usare WORD solo quando hai bisogno di una variabile di dimensioni fisse, come quando stai leggendo / scrivendo da / in un file. Se un pezzo di codice non dipende realmente da una dimensione fissa, allora dovresti usare le normali variabili "int".
Emiliano,

3
La cosa migliore che puoi fare per ottenere dimensioni portatili dovrebbe essere#include <boost/cstdint.hpp>
kizzx2,

11

Ci è consentito 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;
...

1
Questo non è necessario dato l'intestazione standard <stdint.h>(C99 e successive, e qualunque standard C ++ abbia adottato la versione C99 della libreria C).
Keith Thompson,

8

Per i numeri in virgola mobile esiste uno standard (IEEE754) : i float sono a 32 bit e i doppi sono 64. Questo è uno standard hardware, non uno standard C ++, quindi i compilatori potrebbero teoricamente definire float e raddoppiare rispetto ad altre dimensioni, ma in pratica io ' non ho mai visto un'architettura che utilizzava qualcosa di diverso.


2
Tuttavia, la conformità con IEEE 754 (aka IEC 559) è facoltativa in C ++ (probabilmente anche in C, ma non ne sono sicuro). Vedi std :: numeric_limits :: is_iec559.
Ha disegnato la sala il

1
Quindi non hai visto il compilatore di TI per i DSP TMS320C28xx, dove doubleha le stesse dimensioni di float(e intlo stesso char, entrambi sono a 16 bit). Ma hanno un 64 bit long double.
Starblue,

7

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

Wikipedia ha una grande pagina che spiega i vari tipi e il massimo che possono memorizzare: Integer in Computer Science.

Tuttavia, anche con un compilatore C ++ standard, puoi scoprirlo relativamente facilmente usando il seguente frammento di codice:

#include <iostream>
#include <limits>


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

La documentazione per std :: numeric_limits è disponibile su Roguewave . Include una miriade di altri comandi che puoi chiamare per scoprire i vari limiti. Questo può essere usato con qualsiasi tipo arbitrario che trasmette dimensioni, ad esempio std :: streamsize.

La risposta di John contiene la migliore descrizione, poiché sono garantiti. Indipendentemente dalla piattaforma su cui ti trovi, esiste un'altra buona pagina che fornisce maggiori dettagli sul numero di bit che ciascun tipo DEVE contenere: tipi int , che sono definiti nello standard.

Spero che questo possa essere d'aiuto!



7

Puoi usare:

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

datatype = int, long intecc. Sarai in grado di vedere la dimensione per qualunque tipo di dati digiti.


7

Quando si tratta di tipi predefiniti per architetture diverse e compilatori diversi, basta eseguire il seguente codice sulla propria architettura con il proprio compilatore per vedere cosa produce. Di seguito mostra la mia uscita Ubuntu 13.04 (Raring Ringtail) 64 bit g ++ 4.7.3. Inoltre, tieni presente la risposta di seguito, motivo per cui l'output viene ordinato come tale:

"Esistono cinque tipi interi con segno standard: char firmato, 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 <iostream>

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

sizeof(char)non dovrebbe essere incluso.
Ven

3

Come accennato, le dimensioni dovrebbero riflettere l'architettura attuale. Potresti dare un'occhiata in giro limits.hse vuoi vedere come il tuo attuale compilatore sta gestendo le cose.


Grazie, ma vorrei conoscere le dimensioni delle architetture che non ho myselft (come 64 bit). Questo tutorial parla solo di architetture a 32 bit ...
Jérôme,

2

Come altri hanno risposto, gli "standard" lasciano tutti la maggior parte dei dettagli come "implementazione definita" e affermano solo che il tipo "char" è esteso a "char_bis" 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 al doppio - ma può essere più grande su implementazioni più attuali).

Parte delle ragioni per non avere valori molto specifici ed esatti è perché linguaggi come C / C ++ sono stati progettati per essere portabili su un gran numero di piattaforme hardware - Compresi i sistemi informatici in cui la dimensione della parola "char" può essere di 4 bit o 7 bit, o anche un valore diverso dai computer "8- / 16- / 32- / 64-bit" a cui è esposto l'utente medio del computer di casa. (Le dimensioni delle parole qui indicano il numero di bit su cui normalmente funziona il sistema - Ancora una volta, non sono sempre 8 bit come gli utenti del computer di casa possono aspettarsi.)

Se hai davvero bisogno di un oggetto (nel senso di una serie di bit che rappresentano un valore integrale) di un numero specifico di bit, la maggior parte dei compilatori ha qualche metodo per specificarlo; Ma in genere non è portatile, anche tra compilatori realizzati dalla società ame ma per piattaforme diverse. Alcuni standard e pratiche (in particolare 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. (Cioè, se sai che devi 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'intero intervallo desiderato, ma non qualcosa come un tipo "int7" che corrisponderebbe esattamente a 7 bit.)

Nota: molti pacchetti sorgente Un * x hanno utilizzato lo script "./configure" che sonderà le capacità del compilatore / sistema e genererà un Makefile e config.h adeguati. Puoi esaminare alcuni di questi script per vedere come funzionano e come sondano le capacità del comiler / sistema e seguirne l'esempio.


1

Se sei interessato a una soluzione C ++ pura, ho utilizzato modelli e solo codice standard C ++ per definire i tipi in fase di compilazione in base alla loro dimensione in bit. Questo rende la soluzione portatile tra i compilatori.

L'idea alla base è molto semplice: creare un elenco contenente i tipi char, int, short, long, long long (versioni firmate e non firmate) e scansionare l'elenco e usando il modello numeric_limits selezionare il tipo con le dimensioni indicate.

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

Se un tipo non può essere rappresentato, verrà valutato in stdtype :: null_type anche dichiarato in quell'intestazione.

IL CODICE QUI SOTTO VIENE FORNITO SENZA GARANZIA, SI PREGA DI CONTROLLARE DOPPIO.
SONO NUOVO IN METAPROGRAMMING, SONO LIBERO DI MODIFICARE E CORREGGERE QUESTO CODICE.
Testato con DevC ++ (quindi una versione di gcc intorno alla 3.5)

#include <limits>

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<T,S> type
     *
     *  Example:
     *   Creating a list with type int and char: 
     *      typedef type_list<int, type_list<char> > test;
     *      test::value         //int
     *      test::next::value   //char
     */
    template <typename T, typename S> struct type_list
    {
        typedef T value;
        typedef S next;         

    };




    /*
     * Declaration of template struct for selecting a type from the list
     */
    template <typename list, int b, int ctl> struct select_type;


    /*
     * Find a type with specified "b" bit in list "list"
     *
     * 
     */
    template <typename list, int b> 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<cur_type>::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<list, b, cur_type_bits>::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 <int b> struct find_type<null_type, b>
    {   
        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 <typename list, int b, int ctl> struct select_type
    {   
            typedef  typename find_type<typename list::next, b>::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 <typename list, int b> struct select_type<list, b, b>
    {
            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<unsigned char,         \
        type_list<unsigned short,                           \
        type_list<unsigned int,                             \
        type_list<unsigned long,                            \
        type_list<unsigned long long, null_type> > > > >

    #define SIGNED_TYPES type_list<signed char,         \
        type_list<signed short,                         \
        type_list<signed int,                           \
        type_list<signed long,                          \
        type_list<signed long long, null_type> > > > >



    /*
     * 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<UNSIGNED_TYPES, 8>::type  uint8;
    typedef find_type<UNSIGNED_TYPES, 16>::type uint16;
    typedef find_type<UNSIGNED_TYPES, 32>::type uint32;
    typedef find_type<UNSIGNED_TYPES, 64>::type uint64;

    typedef find_type<SIGNED_TYPES, 7>::type    int8;
    typedef find_type<SIGNED_TYPES, 15>::type   int16;
    typedef find_type<SIGNED_TYPES, 31>::type   int32;
    typedef find_type<SIGNED_TYPES, 63>::type   int64;

}


0

Da Alex B Lo standard C ++ non specifica la dimensione dei tipi integrali in byte, ma specifica gli intervalli minimi che devono essere in grado di contenere. È possibile dedurre la dimensione minima in bit dall'intervallo richiesto. È possibile 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 piattaforme tranne quelle 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 dalla norma (pagina 22) sono:

e intervalli di tipi di dati su MSDN:

carattere firmato: da -127 a 127 (nota, non da -128 a 127; questo supporta piattaforme a complemento a 1) carattere senza segno: da 0 a 255 carattere "normale": da -127 a 127 o da 0 a 255 (dipende dalla firma del carattere predefinita) firmato short: da -32767 a 32767 unsigned short: da 0 a 65535 con segno int: da -32767 a 32767 senza segno int: da 0 a 65535 con segno long: da -2147483647 a 2147483647 senza segno long: da 0 a 4294967295 con segno long long: da -9223372036854775807 a 9223372036854775807 lungo senza segno: Da 0 a 18446744073709551615 Un'implementazione C ++ (o C) può definire la dimensione di un tipo in byte dimensione di (tipo) per qualsiasi valore, purché

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

Ad esempio, ecco come troverai l'intervallo massimo per int:

C:

#include <limits.h>
const int min_int = INT_MIN;
const int max_int = INT_MAX;

C ++:

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

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

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

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


0

Noto che tutte le altre risposte qui si sono concentrate quasi esclusivamente sui tipi integrali, mentre l'interrogatore ha anche chiesto dei punti in virgola mobile.

Non penso che lo standard C ++ lo richieda, ma i compilatori per le piattaforme più comuni oggigiorno seguono generalmente lo standard IEEE754 per i loro numeri in virgola mobile. Questo standard specifica quattro tipi di virgola mobile binaria (nonché alcuni formati BCD, per i quali non ho mai visto il supporto nei compilatori C ++):

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

In che modo questa mappa sui tipi C ++, quindi? Generalmente floatutilizza una precisione singola; così, sizeof(float) = 4. Quindi doubleutilizza la doppia precisione (credo che sia la fonte del nome double) e long doublepuò essere una precisione doppia o quadrupla (è quadrupla sul mio sistema, ma sui sistemi a 32 bit potrebbe essere doppia). Non conosco nessun compilatore che offra punti mobili a mezza precisione.

In sintesi, questo è il solito:

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

Divertente che sono arrivato a questa domanda come parte del chiedermi perché Jeff usi più byte di quanti ne abbia bisogno.
Aniruddha Varma,


-2

È possibile utilizzare le variabili fornite da librerie come OpenGL , Qt , ecc.

Ad esempio, Qt fornisce qint8 (garantito su 8 bit su tutte le piattaforme supportate da Qt), qint16, qint32, qint64, quint8, quint16, quint32, quint64, ecc.


1
Non risponde alla domanda
EvilTeach

-8

Su una macchina a 64 bit:

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

2
Su alcune macchine a 64 bit intè di 8 byte, ma l'altro non è garantito. Non c'è nulla che dica che chardovrebbe essere solo 8 bit. È consentito avere sizeof(void*)==4anche se è 64 bit.
skyking

-10

Esistono quattro tipi di numeri interi in base alla dimensione:

  • numero intero breve: 2 byte
  • numero intero lungo: 4 byte
  • long long integer: 8 byte
  • intero: dipende dal compilatore (16 bit, 32 bit o 64 bit)

11
Falso, dipendono tutti dall'architettura, con gli intervalli minimi descritti in una delle altre risposte. Nulla si ferma un'implementazione di avere short, inte longtutti i 32 bit interi.
Matteo Italia,

Non hai nemmeno usato i nomi corretti per i tipi. I nomi usano la parola chiave int, non la parola "intero".
Keith Thompson,
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.