Ricerca…


Char potrebbe essere non firmato o firmato

Lo standard non specifica se char deve essere firmato o non firmato. Diversi compilatori lo implementano in modo diverso, o potrebbero consentire di cambiarlo utilizzando un interruttore della riga di comando.

Dimensione dei tipi integrali

I seguenti tipi sono definiti come tipi interi :

  • char
  • Tipi interi con segno
  • Tipi interi senza segno
  • char16_t e char32_t
  • bool
  • wchar_t

Ad eccezione di sizeof(char) / sizeof(signed char) / sizeof(unsigned char) , che è diviso tra § 3.9.1.1 [basic.fundamental / 1] e § 5.3.3.1 [expr.sizeof], e sizeof(bool) , che è interamente definito dall'implementazione e non ha dimensioni minime, i requisiti minimi di dimensione di questi tipi sono riportati nella sezione § 3.9.1 [basic.fundamental] dello standard, e devono essere dettagliati di seguito.

Dimensione del char

Tutte le versioni dello standard C ++ specificano, nel § 5.3.3.1, che sizeof rendimenti 1 per unsigned char , signed char e char (è implementazione definita se il char tipo è signed o unsigned ).

C ++ 14

char è abbastanza grande da rappresentare 256 valori diversi, per essere adatto alla memorizzazione di unità di codice UTF-8.

Dimensione dei tipi interi con segno e senza segno

Lo standard specifica, in § 3.9.1.2, che nella lista dei tipi interi con signed char standard , costituiti da signed char , short int , int , long int e long long int , ciascun tipo fornirà almeno lo stesso spazio di archiviazione di quelli precedenti nella lista. Inoltre, come specificato nel § 3.9.1.3, ognuno di questi tipi ha un corrispondente intero tipo unsigned standard , unsigned char , unsigned short int , unsigned int , unsigned long int , unsigned long long int , che ha le stesse dimensioni e allineamento di il suo corrispondente tipo firmato. Inoltre, come specificato al § 3.9.1.1, char ha le stesse dimensioni e requisiti di allineamento sia del signed char unsigned char .

C ++ 11

Prima di C ++ 11, long long e unsigned long long non erano ufficialmente parte dello standard C ++. Tuttavia, dopo la loro introduzione a C, in C99, molti compilatori supportati per long long come un tipo intero con unsigned long long esteso e unsigned long long come un tipo intero senza segno esteso , con le stesse regole dei tipi C.

Lo standard garantisce quindi che:

1 == sizeof(char)  == sizeof(signed char) == sizeof(unsigned char)
  <= sizeof(short) == sizeof(unsigned short)
  <= sizeof(int)   == sizeof(unsigned int)
  <= sizeof(long)  == sizeof(unsigned long)
C ++ 11
 <= sizeof(long long) == sizeof(unsigned long long)

Le dimensioni minime specifiche per ciascun tipo non sono indicate dallo standard. Invece, ogni tipo ha un intervallo minimo di valori che può supportare, che è, come specificato nel § 3.9.1.3, ereditato dallo standard C, in §5.2.4.2.1. La dimensione minima di ciascun tipo può essere approssimativamente dedotta da questo intervallo, determinando il numero minimo di bit richiesti; si noti che per qualsiasi piattaforma data, l'intervallo supportato effettivo di qualsiasi tipo potrebbe essere maggiore del minimo. Nota che per i tipi firmati, gli intervalli corrispondono al complemento a uno, non al complemento a due più comunemente usato; questo per consentire a una gamma più ampia di piattaforme di rispettare lo standard.

genere Intervallo minimo Bit minimi richiesti
signed char Da -127 a 127 (- (2 7 - 1) a (2 7 - 1)) 8
unsigned char Da 0 a 255 (da 0 a 2 8 - 1) 8
signed short Da -32.767 a 32.767 (- (2 15 - 1) a (2 15 - 1)) 16
unsigned short Da 0 a 65.535 (da 0 a 2 16 - 1) 16
signed int Da -32.767 a 32.767 (- (2 15 - 1) a (2 15 - 1)) 16
unsigned int Da 0 a 65.535 (da 0 a 2 16 - 1) 16
signed long -2.147.483.647 a 2.147.483.647 (- (2 31 - 1) a (2 31 - 1)) 32
unsigned long Da 0 a 4.294.967.295 (da 0 a 2 32 - 1) 32
C ++ 11
genere Intervallo minimo Bit minimi richiesti
signed long long -9.223.372.036.854.775.807 a 9.223.372.036.854.775.807 (- (2 63 - 1) a (2 63 - 1)) 64
unsigned long long Da 0 a 18.446.744.073,709,551,615 (da 0 a 2 64 - 1) 64

Dato che ogni tipo può essere maggiore del suo requisito di dimensioni minime, i tipi possono differire nelle dimensioni tra le implementazioni. L'esempio più notevole di questo è con i modelli di dati LP64 a 64 bit e LLP64, dove i sistemi LLP64 (come ad esempio Windows a 64 bit) hanno 32 bit ints e long s, e sistemi LP64 (come ad esempio Linux a 64 bit) hanno 32-bit int s e 64 bit long s. A causa di ciò, non si può presumere che i tipi interi abbiano una larghezza fissa su tutte le piattaforme.

C ++ 11

Se sono richiesti tipi interi con larghezza fissa, utilizzare i tipi dall'intestazione <cstdint> , ma si noti che lo standard rende facoltativo per le implementazioni supportare i tipi di larghezza esatta int8_t , int16_t , int32_t , int64_t , intptr_t , uint8_t , uint16_t , uint32_t , uint64_t e uintptr_t .

C ++ 11

Dimensione di char16_t e char32_t

Le dimensioni di char16_t e char32_t sono definite dall'implementazione, come specificato in § 5.3.3.1, con le disposizioni di cui al § 3.9.1.5:

  • char16_t è abbastanza grande da rappresentare qualsiasi unità di codice UTF-16 e ha le stesse dimensioni, signnessness e allineamento di uint_least16_t ; è quindi necessario avere una dimensione di almeno 16 bit.

  • char32_t è abbastanza grande da rappresentare qualsiasi unità di codice UTF-32 e ha le stesse dimensioni, signnessness e allineamento di uint_least32_t ; è quindi necessario avere una dimensione di almeno 32 bit.

Dimensione del bool

La dimensione di bool è definita dall'implementazione e può essere o meno 1 .

Dimensione di wchar_t

wchar_t , come specificato in § 3.9.1.5, è un tipo distinto, il cui intervallo di valori può rappresentare ogni unità di codice distinta del più grande set di caratteri esteso tra le localizzazioni supportate. Ha le stesse dimensioni, compattezza e allineamento di uno degli altri tipi interi, che è noto come tipo sottostante . La dimensione di questo tipo è definita dall'implementazione, come specificato in § 5.3.3.1, e può essere, ad esempio, almeno 8, 16 o 32 bit; se un sistema supporta Unicode, ad esempio, wchar_t deve avere almeno 32 bit (un'eccezione a questa regola è Windows, dove wchar_t è 16 bit per motivi di compatibilità). È ereditato dallo standard C90, ISO 9899: 1990, § 4.1.5, con una sola riformulazione minima.

A seconda dell'implementazione, la dimensione di wchar_t è spesso, ma non sempre, 8, 16 o 32 bit. Gli esempi più comuni di questi sono:

  • Nei sistemi Unix e Unix, wchar_t è a 32 bit e viene solitamente utilizzato per UTF-32.
  • In Windows, wchar_t è a 16 bit e viene utilizzato per UTF-16.
  • Su un sistema che ha solo il supporto a 8 bit, wchar_t è 8 bit.
C ++ 11

Se si desidera il supporto Unicode, si consiglia di utilizzare char per UTF-8, char16_t per UTF-16 o char32_t per UTF-32, invece di utilizzare wchar_t .


Modelli di dati

Come accennato in precedenza, le larghezze dei tipi interi possono differire da una piattaforma all'altra. I modelli più comuni sono i seguenti, con dimensioni specificate in bit:

Modello int long pointer
LP32 (2/4/4) 16 32 32
ILP32 (4/4/4) 32 32 32
LLP64 (4/4/8) 32 32 64
LP64 (4/8/8) 32 64 64

Di questi modelli:

  • Windows a 16 bit utilizzato LP32.
  • Sistemi a 32 bit * nix (Unix, Linux, Mac OSX e altri sistemi operativi Unix) e Windows utilizzano ILP32.
  • Windows a 64 bit utilizza LLP64.
  • I sistemi a 64 bit * nix usano LP64.

Si noti, tuttavia, che questi modelli non sono specificamente menzionati nello standard stesso.

Numero di bit in un byte

In C ++, un byte è lo spazio occupato da un oggetto char . Il numero di bit in un byte è dato da CHAR_BIT , che è definito in climits e deve essere almeno 8. Mentre la maggior parte dei sistemi moderni ha byte da 8 bit, e POSIX richiede che CHAR_BIT sia esattamente 8, ci sono alcuni sistemi dove CHAR_BIT è maggiore di 8 cioè un singolo byte può essere composto da 8, 16, 32 o 64 bit.

Valore numerico di un puntatore

Il risultato del lancio di un puntatore su un numero intero utilizzando reinterpret_cast è definito dall'implementazione, ma "... è destinato a non sorprendere coloro che conoscono la struttura di indirizzamento della macchina sottostante."

int x = 42;
int* p = &x;
long addr = reinterpret_cast<long>(p);
std::cout << addr << "\n"; // prints some numeric address,
                           // probably in the architecture's native address format

Allo stesso modo, il puntatore ottenuto dalla conversione da un intero è anche definito dall'implementazione.

Il modo giusto per memorizzare un puntatore come numero intero è usando i tipi uintptr_t o intptr_t :

// `uintptr_t` was not in C++03. It's in C99, in <stdint.h>, as an optional type
#include <stdint.h>

uintptr_t uip;
C ++ 11
// There is an optional `std::uintptr_t` in C++11
#include <cstdint>

std::uintptr_t uip;

C ++ 11 si riferisce a C99 per la definizione uintptr_t (C99 standard, 6.3.2.3):

un tipo intero senza segno con la proprietà che qualsiasi puntatore valido a void può essere convertito in questo tipo, quindi convertito di nuovo in puntatore a void , e il risultato sarà uguale al puntatore originale.

Mentre, per la maggior parte delle piattaforme moderne, si può assumere uno spazio di indirizzamento piatto e che aritmetica su uintptr_t è equivalente all'aritmetica su char * , è completamente possibile per un'implementazione eseguire qualsiasi trasformazione quando si esegue il cast di void * su uintptr_t finché la trasformazione può essere invertito quando si esegue il ritorno da uintptr_t a void * .

Aspetti tecnici

  • Sui sistemi intptr_t XSI (X / Open System Interfaces), sono richiesti i tipi intptr_t e uintptr_t , altrimenti sono opzionali .

  • Nell'ambito del significato dello standard C, le funzioni non sono oggetti; non è garantito dallo standard C che uintptr_t possa contenere un puntatore a funzione. In ogni caso, la conformità POSIX (2.12.3) richiede che:

    Tutti i tipi di puntatori a funzione devono avere la stessa rappresentazione del puntatore di tipo a void. La conversione di un puntatore di funzione in void * non deve alterare la rappresentazione. Un valore * vuoto risultante da tale conversione può essere riconvertito al tipo di puntatore a funzione originale, utilizzando un cast esplicito, senza perdita di informazioni.

  • C99 §7.18.1:

    Quando i nomi typedef che differiscono solo in assenza o presenza di u iniziali sono definiti, devono indicare i corrispondenti tipi firmati e non firmati come descritto in 6.2.5; un'implementazione che fornisce uno di questi tipi corrispondenti deve fornire anche l'altro.

    uintptr_t potrebbe avere senso se vuoi fare cose ai bit del puntatore che non puoi fare in modo sensato con un numero intero con segno.

Intervalli di tipi numerici

Gli intervalli dei tipi interi sono definiti dall'implementazione. L'intestazione <limits> fornisce il std::numeric_limits<T> che fornisce i valori minimi e massimi di tutti i tipi fondamentali. I valori soddisfano le garanzie fornite dallo standard C attraverso le <climits> e (> = C ++ 11) <cinttypes> .

  • std::numeric_limits<signed char>::min() equivale a SCHAR_MIN , che è minore o uguale a -127.
  • std::numeric_limits<signed char>::max() uguale a SCHAR_MAX , che è maggiore o uguale a 127.
  • std::numeric_limits<unsigned char>::max() equivale a UCHAR_MAX , che è maggiore o uguale a 255.
  • std::numeric_limits<short>::min() equivale a SHRT_MIN , che è minore o uguale a -32767.
  • std::numeric_limits<short>::max() equivale a SHRT_MAX , che è maggiore o uguale a 32767.
  • std::numeric_limits<unsigned short>::max() equivale a USHRT_MAX , che è maggiore o uguale a 65535.
  • std::numeric_limits<int>::min() equivale a INT_MIN , che è minore o uguale a -32767.
  • std::numeric_limits<int>::max() equivale a INT_MAX , che è maggiore o uguale a 32767.
  • std::numeric_limits<unsigned int>::max() equivale a UINT_MAX , che è maggiore o uguale a 65535.
  • std::numeric_limits<long>::min() equivale a LONG_MIN , che è minore o uguale a -2147483647.
  • std::numeric_limits<long>::max() equivale a LONG_MAX , che è maggiore o uguale a 2147483647.
  • std::numeric_limits<unsigned long>::max() uguale a ULONG_MAX , che è maggiore o uguale a 4294967295.
C ++ 11
  • std::numeric_limits<long long>::min() equivale a LLONG_MIN , che è minore o uguale a -9223372036854775807.
  • std::numeric_limits<long long>::max() equivale a LLONG_MAX , che è maggiore o uguale a 9223372036854775807.
  • std::numeric_limits<unsigned long long>::max() equivale a ULLONG_MAX , che è maggiore o uguale a 18446744073709551615.

Per i tipi a virgola mobile T , max() è il valore finito massimo mentre min() è il valore minimo positivo normalizzato. Sono forniti membri aggiuntivi per i tipi a virgola mobile, che sono anche definiti dall'implementazione ma soddisfano determinate garanzie fornite dallo standard C attraverso l'intestazione <cfloat> .

  • Il membro digits10 indica il numero di cifre decimali di precisione.
    • std::numeric_limits<float>::digits10 equivale a FLT_DIG , che è almeno 6.
    • std::numeric_limits<double>::digits10 equivale a DBL_DIG , che è almeno 10.
    • std::numeric_limits<long double>::digits10 equivale a LDBL_DIG , che è almeno 10.
  • Il membro min_exponent10 è il minimo E negativo tale che 10 alla potenza E è normale.
    • std::numeric_limits<float>::min_exponent10 equivale a FLT_MIN_10_EXP , che è al massimo -37.
    • std::numeric_limits<double>::min_exponent10 equivale a DBL_MIN_10_EXP , che è al massimo -37. std::numeric_limits<long double>::min_exponent10 equivale a LDBL_MIN_10_EXP , che è al massimo -37.
  • Il membro max_exponent10 è il massimo E tale che 10 alla potenza E è finito.
    • std::numeric_limits<float>::max_exponent10 equivale a FLT_MIN_10_EXP , che è almeno 37.
    • std::numeric_limits<double>::max_exponent10 equivale a DBL_MIN_10_EXP , che è almeno 37.
    • std::numeric_limits<long double>::max_exponent10 equivale a LDBL_MIN_10_EXP , che è almeno 37.
  • Se il membro is_iec559 è true, il tipo è conforme a IEC 559 / IEEE 754 e il suo intervallo è quindi determinato da tale standard.

Rappresentazione del valore di tipi in virgola mobile

Lo standard richiede che il long double fornisca almeno la stessa precisione del double , che fornisce almeno la stessa precisione del float ; e che un long double può rappresentare qualsiasi valore che una double può rappresentare, mentre un double può rappresentare qualsiasi valore che un float può rappresentare. I dettagli della rappresentazione sono, tuttavia, definiti dall'implementazione.

Per un punto in virgola mobile di tipo T , std::numeric_limits<T>::radix specifica la radice utilizzata dalla rappresentazione di T

Se std::numeric_limits<T>::is_iec559 è vero, la rappresentazione di T corrisponde a uno dei formati definiti da IEC 559 / IEEE 754.

Overflow durante la conversione da numero intero a numero intero con segno

Quando un intero con segno o senza segno viene convertito in un tipo di intero con segno e il suo valore non è rappresentabile nel tipo di destinazione, il valore prodotto è definito dall'implementazione. Esempio:

// Suppose that on this implementation, the range of signed char is -128 to +127 and
// the range of unsigned char is 0 to 255
int x = 12345;
signed char sc = x;   // sc has an implementation-defined value
unsigned char uc = x; // uc is initialized to 57 (i.e., 12345 modulo 256)

Tipo sottostante (e quindi dimensione) di enum

Se il tipo sottostante non è specificato esplicitamente per un tipo di enumerazione senza ambito, viene determinato in un modo definito dall'implementazione.

enum E {
    RED,
    GREEN,
    BLUE,
};
using T = std::underlying_type<E>::type; // implementation-defined

Tuttavia, lo standard richiede che il tipo sottostante di un'enumerazione non sia maggiore di int meno che sia int sia unsigned int non siano in grado di rappresentare tutti i valori dell'enumerazione. Pertanto, nel codice precedente, T potrebbe essere int , unsigned int o short , ma non long long , per fornire alcuni esempi.

Si noti che un enum ha la stessa dimensione (restituita da sizeof ) come tipo sottostante.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow