2013-10-14 18 views
13

Esiste un typedef standard (o MSVC proprietario) per un tipo firmato che può contenere l'intervallo completo dei valori size_t? Cioè su un sistema a 64 bit, sarebbe un intero con segno a 128 bit.typedef per un tipo firmato che può contenere un size_t?

+0

'unsigned long long' –

+0

Oops typo nel titolo. Stavo chiedendo di un tipo firmato. – japreiss

+0

Nella remota possibilità che il motivo per cui vuoi un tipo firmato sia sovraccarico/escape con un significato speciale, potresti considerare il wrapper 'boost :: optional <>'. –

risposta

10

In generale non è possibile definire un tipo di questo tipo. È perfettamente legale per un'implementazione rendere size_t il più grande tipo non firmato supportato, il che significherebbe che nessun tipo firmato può contenere tutti i suoi valori.

ptrdiff_t non è necessariamente sufficientemente ampio. È il risultato della sottrazione di due puntatori, ma non c'è nulla che dice che una sottrazione del puntatore non possa traboccare. Vedere la sezione 5.7 dello standard ++ C:

Quando due puntatori a elementi dello stesso oggetto array vengono sottratti, il risultato è la differenza tra gli indici dei due elementi di matrice . Il tipo del risultato è un tipo integrale con firma firmato definito dall'implementazione; questo tipo deve essere dello stesso tipo definito come std::ptrdiff_t nell'intestazione <cstddef> (18.2). Come con qualsiasi altro overflow aritmetico , se il risultato non si adatta nello spazio fornito, il comportamento non è definito.

Il più grande tipo firmato è intmax_t, definito nel <stdint.h> o <cstdint>. Questa è una funzionalità C99 e C++ 11 è stato il primo standard C++ a incorporare la libreria standard C99, quindi il compilatore potrebbe non supportarlo (e probabilmente MSVC non lo supporta). Se c'è un tipo firmato abbastanza largo da contenere tutti i possibili valori di tipo size_t, allora intmax_t è (anche se lo potrebbe essere un tipo firmato più stretto che si qualifica anche).

È inoltre possibile utilizzare long long, che è un tipo firmato garantito almeno da 64 bit (e molto probabilmente uguale a intmax_t). Anche se non è sufficientemente ampio da contenere tutti i possibili valori di tipo size_t, sarà quasi certo che tutti i valori rilevanti sono pertinenti a size_t, a meno che l'implementazione non supporti effettivamente oggetti più grandi di 8 exabyte (ovvero 8192 petabyte o 8388608 terabyte).

(Nota, sto utilizzando le definizioni binarie di "volta a valutare", "peta-", e "tera-", che sono di dubbia validità.)

+1

* "e MSVC molto probabilmente non" * - Come nota a margine, i nuovi tipi di interi erano effettivamente una delle poche funzionalità di C++ 11 che la libreria standard * MSVC * aveva da * 2010 *. –

+0

Inoltre, se non si è sicuri delle dimensioni che si otterranno su una determinata piattaforma, aggiungere un: 'static_assert (sizeof (intmax_t)> sizeof (size_t)," Impossibile ottenere un tipo firmato che garantisca una dimensione_t ");' così il compilatore ti avviserà se stai per entrare nei guai. –

2

presumo avete bisogno di questo tipo per un po ' tipo di aritmetica dei puntatori. È molto improbabile che tu abbia bisogno di nient'altro che lo std::ptrdiff_t. L'unico caso in cui questo svolgerà un ruolo su una macchina moderna è quando ci si trova in modalità a 32 bit e si sta lavorando su un set di dati con più di 2^31 byte. (Questo non sarà nemmeno possibile su Windows senza un lavoro speciale.) Non sarai in grado di utilizzare due array di quella dimensione allo stesso tempo. In questo caso, probabilmente dovresti comunque lavorare in modalità 64 bit.

In modalità a 64 bit molto probabilmente non sarà un problema per i prossimi 40 anni circa con l'attuale velocità di sviluppo della memoria. E quando si diventa un problema, quindi compilare il codice in modalità 128-bit e continuerà a correre. ;)

2

Se si desidera un tipo standard che può contenere il valore massimo del sistema, forse il <cstdint> (dal C++ 11) potrebbe aiutare.

C'è un typedef in quell'intestazione che contiene il tipo intero di larghezza massima, il tipo è intmax_t. Lo intmax_t per gli interi con segno e lo uintmax_t per quelli senza segno è il più grande intero pienamente supportato dall'architettura.

Quindi, supponiamo che sei in un'architettura a 64 bit, la seguente istruzione:

std::cout << "intmax_t is same int64_t? " 
      << (std::is_same<intmax_t, int64_t>::value ? "Yes" : "No"); 

uscita sarà:

intmax_t è lo stesso int64_t? Sì

Live demo.

Spero che aiuti.

Problemi correlati