Assegnazione di un valore a un lungo numero lungo utilizzando GCC su SPARC Solaris
Domanda
Mi sono imbattuto in qualcosa che penso piuttosto strano. Il programma di test
int main(int argc, char* argv[])
{
cout<<"hello"<<endl;
long unsigned l = 0x12345678;
long long unsigned ll = 0x12345678;
cout<<sizeof(l)<<endl;
cout<<sizeof(ll)<<endl;
};
L'output è:
hello
4
8
Nessuna sorpresa lì. Il long int
ha una dimensione di 4 byte e il long long
ha una dimensione di 8 byte. Tuttavia, quando lo cambio in modo che il lungo lungo sia assegnato
long long unsigned ll = 0x123456789;
Al momento della compilazione che ottengo
error: integer constant is too large for "long" type
Ora questo stesso test fa Compilare se formo una costruzione a 64 bit usando l'opzione -m64
. Sto facendo qualcosa di sbagliato o questo è un bug in GCC?
Soluzione
Cambiarlo in
long long unsigned ll = 0x123456789ULL; // notice the suffix
Senza il suffisso, il letterale è più grande del massimo unsigned long
valore sulla tua macchina e questo, secondo C ++ 03 (ma non C ++ 11, che ha long long
), è un comportamento indefinito. Ciò significa che tutto può accadere, incluso un errore a tempo di compilazione.
Inoltre non vale nulla che non ci sia long long
In C ++ 03, quindi non è garantito per funzionare, stai facendo affidamento su un'estensione. Probabilmente è meglio che tu sia invece uscito usando C ++ 11.
Altri suggerimenti
La cosa qui è che molte persone sembrano guardare una riga di codice come il tuo:
unsigned long long ll = 0x123456789; /* ANTI-PATTERN! Don't do this! */
e motivo "Oh, il tipo è unsigned long long
, quindi il valore è unsigned long long
E viene assegnato ", ma non è così che funziona. avere il proprio tipo, ciò non dipende dal contesto in cui vengono utilizzati. E il tipo di letterali interi è int
.
Questo è lo stesso errore di quando la gente lo fa:
const double one_third = 1 / 3; /* ANTI-PATTERN! Don't do this! */
Pensare "Il tipo a sinistra è double
, quindi questo dovrebbe assegnare 0,3333333 ... ". Questo è solo (di nuovo!) Non come funziona. I tipi di letterali divisi sono ancora int
, quindi il lato destro valuta esattamente 0, che viene poi convertito in double
e conservato nel one_third
variabile.
Per qualche ragione, questo comportamento è profondamente non intuitivo per molte persone, motivo per cui ci sono molte varianti della stessa domanda.