2016-03-22 8 views
12

In C++ 11 vengono forniti tipi di interi a larghezza fissa, ad esempio std::int32_t e std::int64_t, che sono opzionali e quindi non ottimali per la scrittura di codice multipiattaforma. Tuttavia, abbiamo anche ottenuto varianti non opzionali per i tipi: ad es. le varianti "veloci", ad es. std::int_fast32_t e std::int_fast64_t, nonché le varianti "di dimensioni più piccole", ad es. std::int_least32_t, che hanno entrambi almeno il numero specificato di bit in dimensione.C'è un motivo per usare std :: int_fast32_t o std :: int_fast16_t di C++ 11 su int in codice multipiattaforma?

Il codice su cui sto lavorando fa parte di una libreria multipiattaforma basata su C++ 11, che supporta la compilazione sui più famosi compilatori Unix/Windows/Mac. Una domanda che è venuta fuori è se c'è un vantaggio nel sostituire i tipi interi esistenti nel codice con i tipi interi a larghezza fissa C++ 11.

Uno svantaggio dell'utilizzo di variabili come std::int16_t e std::int32_t è la mancanza di una garanzia che sono disponibili, in quanto vengono forniti solo se l'implementazione supporta direttamente il tipo (secondo http://en.cppreference.com/w/cpp/types/integer).

Tuttavia, poiché int è almeno 16 bit e 16 bit sono sufficientemente grandi per gli interi utilizzati nel codice, per quanto riguarda l'utilizzo di std::int_fast16_t su int? Fornisce un vantaggio per sostituire tutti i tipi int di std::int_fast16_t e tutti gli unsigned int di std::uint_fast16_t in questo modo o non è necessario?

Anologously, se sapendo che tutte le piattaforme e compilatori supportati presentano una int di almeno 32 bit dimensioni, ha senso sostituirli rispettivamente std::int_fast32_t e std::uint_fast32_t?

+4

Il tuo "svantaggio" sembra essere basato su un'ipotesi. Chi dice che 'std :: int16_t' e' std :: int32_t' potrebbero andare via? Dopo tutto, sono richiesti dallo * standard *. –

+3

Se vuoi essere sicuro che il tuo int abbia almeno una larghezza di 32 bit, fallo. Normale 'int' non fornisce tale garanzia. –

+3

@GregHewgill sono facoltativi. Intendevo che potrebbero non essere supportati nelle versioni future di un sistema operativo e di un compilatore, se prima erano supportati. Non sono a conoscenza di alcun OS e compilatore che non fornisce std :: int16_t e std :: int32_t ma poiché sono solo non facoltativi se un numero intero di queste dimensioni esiste già in modo nativo, la loro esistenza non può essere garantita. Vedi anche: http: // StackOverflow.it/questions/32155759/state-of-support-per-the-optional-fixed-width-integer-types-introduce-in-c11 dove puoi rispondere se ne sai di più :) – Ident

risposta

20

int può essere 16, 32 o anche 64 bit su computer e compilatori correnti. In futuro, potrebbe essere più grande (ad esempio, 128 bit).

Se il tuo codice è ok, vai con esso.

Se il codice è stato testato e funziona solo con 32 bit inte, è consigliabile utilizzare int32_t. Quindi il codice fallirà in fase di compilazione anziché in fase di esecuzione quando viene eseguito su un sistema che non dispone di 32 bit (cosa estremamente rara oggi).

int_fast32_t è quando avete bisogno di almeno 32 bit, ma vi preoccupate molto delle prestazioni. Su hardware che un intero a 32 bit viene caricato come un intero a 64 bit, quindi reindirizzato a un numero intero a 32 bit in un processo ingombrante, il numero int_fast_32_t potrebbe essere un numero intero a 64 bit. Il costo di questo è che su piattaforme oscure, il tuo codice si comporta in modo molto diverso.

Se non si esegue il test su tali piattaforme, vorrei sconsigliarlo.

L'interruzione delle attività in fase di compilazione è in genere preferibile a interruzioni in fase di esecuzione. Se e quando il codice viene effettivamente eseguito su un processore oscuro che richiede queste funzionalità, quindi risolverlo. Si applica la regola "Probabilmente non ne avrai bisogno".

Essere prudenti, generare errori precoci sull'hardware su cui non si è verificato il test e quando è necessario eseguire il porting su detto hardware, eseguire il lavoro e i test richiesti per essere affidabili.

In breve:

Usa int_fast##_t se e solo se si è testato il codice (e continuerà a testarlo) su piattaforme dove la dimensione int varia, e si è dimostrato che il miglioramento delle prestazioni vale la pena quella manutenzione futura.

L'utilizzo di int##_t con dimensioni comuni ## significa che il codice non verrà compilato su piattaforme su cui non è stato eseguito il test. Questo è buono; il codice non testato non è affidabile e il codice inaffidabile è generalmente peggio che inutile.

Senza usare int32_t, e l'utilizzo di int, il codice a volte hanno int s che sono 32 e, a volte interi che sono 64 (e in teoria più), e qualche volta int s che sono 16. Se si è disposti a testare e supportare ogni caso in ogni tale int, andare per questo.

Si noti che gli array di int_fast##_t possono avere problemi di cache: potrebbero essere irragionevolmente grandi. Ad esempio, int_fast16_t potrebbe essere 64 bit. Una serie di poche migliaia o milioni di loro potrebbe essere individualmente veloce con cui lavorare, ma i fallimenti della cache causati dalla loro mole potrebbero renderli più lenti nel complesso; e il rischio che le cose vengano scambiate per lo storage più lento.

int_least##_t può essere più veloce in questi casi.

Lo stesso vale, doppiamente, per i dati trasmessi in rete e archiviati, oltre all'ovvio problema che i dati di rete/file solitamente devono seguire formati stabili su modifiche del compilatore/hardware. Questa, tuttavia, è una domanda diversa.

Tuttavia, quando si utilizzano tipi interi a larghezza fissa, è necessario prestare particolare attenzione al fatto che int, long, ecc. Hanno ancora la stessa larghezza di prima. La promozione di interi continua ancora in base alla dimensione di int, che dipende dal compilatore che stai utilizzando. Un numero intero nel tuo codice sarà di tipo int, con la larghezza associata. Questo può portare a comportamenti indesiderati se si compila il codice usando un compilatore diverso. Per informazioni più dettagliate: https://stackoverflow.com/a/13424208/3144964

+0

Innanzitutto, grazie per la risposta rapida e utile! Sfortunatamente hai scritto questa risposta così in fretta che stavo ancora correggendo un errore che ho fatto nella mia domanda (ho dimenticato di menzionare l'ipotesi che gli int i nei sistemi supportati siano almeno 32 bit) e ora la domanda viene espansa un po '. Perdonami per quello. – Ident

+0

@ident Ho aggiunto un paragrafo o due. – Yakk

+1

Dovresti indicare gli use case per 'int_leastxx *' e 'int_fast'. Il più veloce potrebbe non essere il migliore se si devono memorizzare tali numeri interi, nulla impedisce che sizeof (int_fast32_t) sia irragionevolmente grande, che a causa della cache potrebbe effettivamente renderlo più lento di 'int_least32_t'. – sbabbi

1

Mi sono appena reso conto che l'OP sta solo chiedendo di int_fast##_t non int##_t poiché il successivo è facoltativo. Tuttavia, terrò la risposta saltellando potrebbe aiutare qualcuno.


Vorrei aggiungere qualcosa. Gli interi a dimensione fissa sono così importanti (o addirittura obbligatori) per la creazione di API per altre lingue. Un esempio è quando quando si vogliono le funzioni pInvoke e si passano loro i dati in una DLL C++ nativa da un codice gestito .NET per esempio. In .NET, è garantito che la dimensione int sia fissa (penso che sia a 32 bit). Quindi, se hai usato int in C++ ed è stato considerato come 64 bit anziché 32 bit, questo potrebbe causare problemi e ridurre la sequenza di strutture avvolte.

Problemi correlati