Come si legge nel titolo della domanda, l'assegnazione di 2^31 a una variabile intera a 32 bit con segno e senza segno fornisce un risultato imprevisto.Risultato strano dopo l'assegnazione di 2^31 a una variabile intera a 32 bit con segno e senza segno
Ecco il programma corto (in C++
), che ho fatto per vedere cosa sta succedendo:
#include <cstdio>
using namespace std;
int main()
{
unsigned long long n = 1<<31;
long long n2 = 1<<31; // this works as expected
printf("%llu\n",n);
printf("%lld\n",n2);
printf("size of ULL: %d, size of LL: %d\n", sizeof(unsigned long long), sizeof(long long));
return 0;
}
ecco l'output:
MyPC/# c++ test.cpp -o test
MyPC/# ./test
18446744071562067968 <- Should be 2^31 right?
-2147483648 <- This is correct (-2^31 because of the sign bit)
size of ULL: 8, size of LL: 8
Ho poi aggiunto un'altra funzione p()
, ad essa :
void p()
{
unsigned long long n = 1<<32; // since n is 8 bytes, this should be legal for any integer from 32 to 63
printf("%llu\n",n);
}
In fase di compilazione e esecuzione, questo è ciò che confonde d ancora di più:
MyPC/# c++ test.cpp -o test
test.cpp: In function ‘void p()’:
test.cpp:6:28: warning: left shift count >= width of type [enabled by default]
MyPC/# ./test
0
MyPC/
Perché il compilatore dovrebbe lamentarsi del numero di turni a sinistra troppo grande? sizeof(unsigned long long
) restituisce 8, quindi non significa che 2^63-1 è il valore massimo per quel tipo di dati?
Mi ha colpito che forse n * 2 e n < < 1, non si comportano sempre allo stesso modo, così ho provato questo:
void s()
{
unsigned long long n = 1;
for(int a=0;a<63;a++) n = n*2;
printf("%llu\n",n);
}
Questo dà il valore corretto di 2^63 come l'output che è 9223372036854775808
(l'ho verificato usando python). Ma cosa c'è di sbagliato nel fare una merda sinistra?
Uno spostamento aritmetico sinistro da n equivale a moltiplicare per 2 n (il cui valore non trabocchi)
- Wikipedia
Il valore non è traboccante , apparirà solo un segno meno poiché il valore è 2^63 (tutti i bit sono impostati).
Non riesco ancora a capire cosa sta succedendo con il turno di sinistra, qualcuno può spiegarlo per favore?
PS: Questo programma è stato eseguito su una zecca a 32 bit del sistema con Linux (se che aiuta)
Questo dovrebbe essere 'unsigned long long n = 1ULL << 31;' – kirilloid
dio! è stato così facile ?! Perché non ci ho pensato. comunque, sì 1ULL << 31 funziona. quindi grazie! – Rushil