`Long` è garantito che abbia almeno 32 bit?

Dalla mia lettura dello standard C ++, ho sempre capito che le dimensioni dei tipi fondamentali integrali in C ++ erano le seguenti:

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

Ho dedotto questo dal 3.9.1 / 2:

  1. Esistono quattro tipi di interi con segno: “signed char”, “short int”, “int” e “long int”. In questo elenco, ciascun tipo fornisce almeno lo stesso spazio di archiviazione di quelli che lo precedono nell’elenco. Gli elementi semplici hanno le dimensioni naturali suggerite dall’architettura dell’ambiente di esecuzione

Inoltre, la dimensione del char è descritta in 3.9.1 / come:

  1. […] abbastanza grande da memorizzare qualsiasi membro del set di caratteri di base dell’implementazione.

1.7 / 1 definisce questo in termini più concreti:

  1. L’unità di memoria fondamentale nel modello di memoria C + + è il byte. Un byte è almeno abbastanza grande da contenere qualsiasi membro del set di caratteri di esecuzione di base ed è composto da una sequenza contigua di bit, il cui numero è definito dall’implementazione.

Questo mi porta alla seguente conclusione:

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

dove sizeof ci dice quanti byte è il tipo. Inoltre, è definito dall’implementazione quanti bit ci sono in un byte. Molti di noi sono probabilmente abituati a trattare con byte da 8 bit, ma lo standard dice che ci sono n bit in un byte.


In questo post , Alf P. Steinbach dice:

lungo è garantito (almeno) 32 bit.

Questo fa schifo di fronte a tutto ciò che capisco la dimensione dei tipi fondamentali in C ++ secondo lo Standard. Normalmente avrei semplicemente scartato questa affermazione, dato che un principiante si sbagliava, ma poiché questo era Alf, ho deciso che valeva la pena indagare ulteriormente.

Allora, che cosa dici? Una durata garantita dallo standard è di almeno 32 bit? Se è così, si prega di essere specifici su come è fatta questa garanzia. Io proprio non lo vedo.

  1. Lo Standard C ++ dice specificatamente che per conoscere C ++ devi sapere C (1.2 / 1) 1

  2. Lo standard C ++ definisce implicitamente il limite minimo dei valori che un long può contenere per essere LONG_MINLONG_MAX 2

Quindi, indipendentemente da quanto sia long , deve essere abbastanza grande da contenere LONG_MIN a LONG_MAX.

Ma Alf e altri sono specifici che un lungo deve essere almeno di 32 bit. Questo è quello che sto cercando di stabilire. Lo standard C ++ è esplicito che il numero di bit in un byte non è specificato (potrebbe essere 4, 8, 16, 42) Quindi, come è fatta la connessione dall’essere in grado di ospitare i numeri LONG_MIN-LONG_MAX ad almeno 32 bit ?


(1) 1.2 / 1: I seguenti documenti di riferimento sono indispensabili per l’applicazione di questo documento. Per i riferimenti datati, si applica solo l’edizione citata. Per i riferimenti non datati, si applica l’ultima edizione del documento di riferimento (compresi eventuali emendamenti).

  • ISO / IEC 2382 (tutte le parti), Tecnologia dell’informazione – Vocabolario
  • ISO / IEC 9899: 1999, Linguaggi di programmazione – C
  • ISO / IEC 10646-1: 2000, Tecnologia dell’informazione – Set di caratteri codificati multicanale universale (UCS) – Parte 1: Architettura e piano multilingue multilingue

(2) Definito in come:

 LONG_MIN -2147483647 // -(2^31 - 1) LONG_MAX +2147483647 // 2^31 - 1 

C ++ utilizza i limiti definiti nello standard C (C ++: 18.3.2 (c.limits), C: 5.2.4.2.1):

 LONG_MIN -2147483647 // -(2^31 - 1) LONG_MAX +2147483647 // 2^31 - 1 

Quindi è garantito che una lunghezza è almeno di 32 bit.

E se vuoi seguire il lungo percorso tortuoso per stabilire se LONG_MIN / LONG_MAX sono rappresentabili di long , devi guardare 18.3.1.2 (numeric.limits.members) nello standard C ++:

 static constexpr T min() throw(); // Equivalent to CHAR_MIN, SHRT_MIN, FLT_MIN, DBL_MIN, etc. static constexpr T max() throw(); // Equivalent to CHAR_MAX, SHRT_MAX, FLT_MAX, DBL_MAX, etc. 

Ho spostato le note nel commento, quindi non è esattamente ciò che appare nello standard. Ma fondamentalmente implica che std::numeric_limits::min()==LONG_MIN==(long)LONG_MIN e std::numeric_limits::max()==LONG_MAX==(long)LONG_MAX .

Quindi, anche se lo standard C ++ non specifica la rappresentazione bit a bit dei numeri negativi (firmati), deve essere sia twos-complemento che richiedere 32 bit di memoria in totale, oppure ha un bit di segno esplicito che significa che ha 32-bit di archiviazione anche.

La risposta è definitivamente SÌ. Leggi il mio OP e tutti i commenti per capire esattamente perché, ma ecco la versione breve. Se dubiti o interroghi tutto ciò, ti incoraggio a leggere l’intero thread e tutti i commenti. Altrimenti, accettalo come vero:

  1. Lo standard C ++ include parti dello standard C, comprese le definizioni per LONG_MIN e LONG_MAX
  2. LONG_MIN è definito come non superiore a -2147483647
  3. LONG_MAX è definito come non inferiore a +2147483647
  4. Nei tipi integrali C ++ sono memorizzati in binario nella rappresentazione sottostante
  5. Per rappresentare -2147483647 e +2147483647 in binario, sono necessari 32 bit.
  6. A C ++ long è garantito che sia in grado di rappresentare la gamma minima LONG_MIN attraverso LONG_MAX

Pertanto un long deve essere almeno di 32 bit 1 .

MODIFICARE:

LONG_MIN e LONG_MAX hanno valori con magnitudini dettate dallo standard C (ISO / IEC 9899: TC3) nella sezione §5.2.4.2.1:

[…] I loro valori definiti dall’implementazione devono essere uguali o maggiori in magnitudine […] (valore assoluto) a quelli mostrati, con lo stesso segno […]

 — minimum value for an object of type long int LONG_MIN -2147483647 // -(2 ^ 31 - 1) — maximum value for an object of type long int LONG_MAX +2147483647 // 2 ^ 31 - 1 

1 32 bit : questo non significa che sizeof (long) >= 4 , perché un byte non è necessariamente 8 bit. Secondo lo standard, un byte è un numero di bit non specificato (definito dalla piattaforma). Mentre molti lettori troveranno questo strano, c’è un vero hardware su cui CHAR_BIT è 16 o 32.

Lo standard C ++ rileva che i contenuti di sono gli stessi dell’intestazione C (18.2.2 in ISO C ++ 03 doc).

Sfortunatamente, non ho una copia dello standard C esistente pre-C ++ 98 (cioè C90), ma in C99 (sezione 5.2.4.2.1), deve avere almeno questi valori minimi . Non penso che sia cambiato da C90, tranne C99 aggiungendo i long long .

 — minimum value for an object of type long int LONG_MIN -2147483647 // −(2^31 − 1) — maximum value for an object of type long int LONG_MAX +2147483647 // 2^31 − 1 — maximum value for an object of type unsigned long int ULONG_MAX 4294967295 // 2^32 − 1 — minimum value for an object of type long long int LLONG_MIN -9223372036854775807 // −(2^63− 1) 

Ma Alf e altri sono specifici che un lungo deve essere almeno di 32 bit. Questo è quello che sto cercando di stabilire. Lo standard C ++ è esplicito che il numero di bit in un byte non è specificato. Potrebbe essere 4, 8, 16, 42 … Quindi, come è fatta la connessione dall’essere in grado di contenere i numeri LONG_MIN-LONG_MAX fino ad almeno 32 bit?

Avete bisogno di 32 bit nella rappresentazione del valore per ottenere almeno tanti bit bittern. E poiché C ++ richiede una rappresentazione binaria di interi (linguaggio esplicito in tal senso nello standard, §3.9.1 / 7), QED

Sì, lo standard C ++ è esplicito che il numero di bit in un byte non è specificato. Il numero di bit in un lungo non è specificato, neanche.

L’impostazione di un limite inferiore su un numero non lo specifica .

Lo standard C ++ dice, in un unico punto:

 1 == sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long). 

Dice, in effetti, in un altro luogo, tramite l'inclusione dello standard C:

 CHAR_BITS >= 8; SHORT_BITS >= 16; INT_BITS >= 16; LONG_BITS >= 32 

(ad eccezione di AFAIK, gli identificatori SHORT_BITS, INT_BITS e LONG_BITS non esistono e questi limiti sono desunti dai requisiti per i valori minimi sui tipi).

Questo deriva dal fatto che un certo numero di bit è richiesto matematicamente per codificare tutti i valori nell'intervallo LONG_MIN..LONG_MAX (ad esempio per lunghi).

Infine, i corti, gli interi e i long devono essere tutti costituiti da un numero intero di caratteri; sizeof () riporta sempre un valore integrale. Inoltre, l'iterazione tramite la memoria char di char deve accedere ad ogni bit, il che pone alcune limitazioni pratiche.

Questi requisiti non sono incoerenti in alcun modo . Qualsiasi dimensione che soddisfi i requisiti è OK.

C'erano macchine molto tempo fa con una dimensione nativa di 36 bit. Se dovessi eseguire il porting di un compilatore C ++, potresti decidere legalmente di avere 9 bit in un char, 18 in short e int e 36 in long. Si potrebbe anche decidere legalmente di avere 36 bit in ognuno di questi tipi, per la stessa ragione per cui oggi è ansible avere 32 bit in un int su un tipico sistema a 32 bit. Esistono implementazioni del mondo reale che utilizzano caratteri a 64 bit.

Vedi anche le sezioni 26.1-6 e 29.5 del C ++ FAQ Lite .