Ho fatto qualche test stupido sulla manipolazione dei bit e ho trovato questo problema. Eseguo questo codice:Bit di spostamento sinistro in c
int main(){
unsigned int i;
for (i=1; i<34; i++)
{
unsigned long temp = i;
unsigned long mul = 1;
unsigned long val;
unsigned long one = 1;
// Way 1
while (temp--)
mul = mul << one;
// Way 2
val = (one<<i);
printf(" \n 1<<%i \n mul: 0x%X , val: 0x%X\n",i, mul, val);
}
}
Ovviamente, quando i> 31, verrà generato un overflow. Penso che entrambe le parti del codice (way1 e way2) dovrebbero produrre lo stesso risultato. Ma ottengo questo (alla fine):
/* ... correct results from i=1 to i=31 ... */
1<<30
mul: 0x40000000 , val: 0x40000000
1<<31
mul: 0x80000000 , val: 0x80000000
1<<32
mul: **0x0** , val: **0x1**
1<<33
mul: **0x0** , val: **0x2**
Perché, se entrambe le istruzioni sono lasciati turni, il programma produce risultati diversi? Sembra che la parte way2 produca un round shift, ma non so perché, penso davvero che "mul" abbia sempre il valore corretto.
compilo sotto una macchina 32bit Intel, versione di gcc 4.4.7
Il risultato di un'operazione di spostamento con una quantità di spostamento maggiore della larghezza dell'operando non è definito per lo standard C. –
Solo un parere, ma direi che in questi casi: 'mul << one' e' one << i', in realtà è meglio usare semplicemente '1' piuttosto che dargli il nome' one'. –
Questo è il problema, sì. In questo caso, probabilmente è ANDs l'operando giusto con 0x3F prima di fare lo shft. –